說到 AI 輔助編碼,OpenAI ChatGPT 5Grok 4 是 2025 年最熱門的兩款工具。兩者都聲稱能夠以高精度和高效率編寫 Python 程式碼,但在實際場景中,究竟哪一款能夠真正交付更簡潔、更易於維護的腳本呢?

在本文中,我們將在多項 Python 挑戰賽中對 ChatGPT 5Grok 4 進行比較。我們將考察它們的程式碼正確性可讀性執行速度以及在應對棘手問題時的適應性

為什麼要比較 ChatGPT 5 和 Grok 4 的 Python 版本?

Python 仍然是 AI、自動化和資料科學領域的首選語言。現在,許多開發者依靠 AI 來加速他們的編碼工作流程、更快地進行調試,甚至從頭開始產生完整的應用程式。

雖然 ChatGPT 長期以來一直主導著這一領域,但 Grok 也因其程式碼清晰輸出簡潔而備受關注。兩者採用不同的訓練理念:ChatGPT 注重推理,而 Grok 則注重簡潔。

測試 OpenAI ChatGPT 5 和 Grok 4

我們將透過 10 個 Python 程式碼測試用例來比較這兩個 AI:

  1. 基本腳本(偶數求和)
  2. 資料處理(CSV 總計)
  3. 演算法問題(第一個非重複字元)
  4. API 整合(比特幣價格取得)
  5. 網頁抓取(Hacker News 標題)
  6. 檔案壓縮(.txt 檔案壓縮)
  7. 影像處理(調整 JPEG 大小)
  8. 多線程(並發下載)
  9. 資料庫互動(SQLite CRUD)
  10. 單元測試(素數測試)

所有測試題目將完全相同,並提交給 ChatGPT 5 和 Grok 4。您可以自行執行測試來驗證結果。

Python 挑戰 1 - 基礎腳本

挑戰 1 提示:

寫一個 Python 腳本,讀取一個整數列表並輸出偶數總和。

挑戰 1 GPT 5 代碼:

 1# Script to read a list of integers and output the sum of even numbers
 2def sum_of_even_numbers(numbers):
 3    return sum(num for num in numbers if num % 2 == 0)
 4
 5if __name__ == "__main__":
 6    # Read input from the user
 7    try:
 8        numbers = list(map(int, input("Enter integers separated by spaces: ").split()))
 9        total_even = sum_of_even_numbers(numbers)
10        print("Sum of even numbers:", total_even)
11    except ValueError:
12        print("Please enter valid integers only.")

挑戰 1 Grok 4 代碼:

 1# Read a line of input containing space-separated integers
 2input_line = input("Enter a list of integers separated by spaces: ")
 3
 4# Convert the input string into a list of integers
 5numbers = list(map(int, input_line.split()))
 6
 7# Initialize sum of even numbers
 8even_sum = 0
 9
10# Iterate through the list and add even numbers to the sum
11for num in numbers:
12    if num % 2 == 0:
13        even_sum += num
14
15# Output the sum
16print("Sum of even numbers:", even_sum)

挑戰 1 觀察:

  • GPT 5 速度:反應速度非常快,幾乎即時完成。
  • GPT 5 代碼:提供更短、更優雅的程式碼,包含入口點和註解。
  • Grok 4 速度:反應速度較慢,「思考」時間稍長(約 2 秒)。
  • Grok 4 代碼:提供稍長的代碼,沒有入口點,但包含註釋。

Python 挑戰 2 - 資料處理

挑戰 2 提示:

載入交易記錄的 CSV 檔案並列印每件產品的總銷售額。

挑戰 2 GPT 5 代碼:

 1import csv
 2from collections import defaultdict
 3
 4def total_sales_per_product(csv_file):
 5    sales = defaultdict(float)
 6
 7    with open(csv_file, newline='', encoding='utf-8') as f:
 8        reader = csv.DictReader(f)
 9        for row in reader:
10            try:
11                product = row['product']
12                quantity = float(row['quantity'])
13                price = float(row['price'])
14                sales[product] += quantity * price
15            except (KeyError, ValueError):
16                print(f"Skipping invalid row: {row}")
17
18    return sales
19
20if __name__ == "__main__":
21    file_path = "transactions.csv"  # Change to your file path
22    sales_totals = total_sales_per_product(file_path)
23
24    print("Total Sales Per Product:")
25    for product, total in sales_totals.items():
26        print(f"{product}: ${total:,.2f}")

挑戰 2 Grok 4 代碼:

 1import pandas as pd
 2
 3# Prompt user for the CSV file path
 4file_path = input("Enter the path to the CSV file: ")
 5
 6# Load the CSV file into a DataFrame
 7df = pd.read_csv(file_path)
 8
 9# Assuming the CSV has columns 'Product' and 'Sales'
10# Group by 'Product' and sum the 'Sales'
11total_sales = df.groupby('Product')['Sales'].sum()
12
13# Print the total sales per product
14print("Total sales per product:")
15print(total_sales)

挑戰 2 觀察:

  • GPT 5 速度:反應速度非常快,幾乎是即時的。
  • GPT 5 代碼:提供了稍長且優雅的代碼,包含入口點,但沒有註釋。
  • Grok 4 速度:反應速度較慢,「思考」起來稍長(約 13 秒)。
  • Grok 4 程式碼:提供了更簡單的程式碼,沒有入口點,但包含註解。

Python 挑戰 3 - 演算法題

挑戰 3 提示:

給定一個字串,傳回第一個非重複字元。

挑戰 3 GPT 5 代碼:

 1def first_non_repeating_char(s):
 2    from collections import Counter
 3    counts = Counter(s)
 4
 5    for char in s:
 6        if counts[char] == 1:
 7            return char
 8    return None  # If no non-repeating character found
 9
10# Example usage
11text = "swiss"
12result = first_non_repeating_char(text)
13if Code:
14    print(f"The first non-repeating character is: '{result}'")
15else:
16    print("No non-repeating character found.")

挑戰 3 Grok 4 代碼:

 1import collections
 2
 3def first_non_repeating_char(s):
 4    """
 5    Returns the first non-repeating character in the string.
 6    If no such character exists, returns None.
 7    """
 8    count = collections.Counter(s)
 9    for char in s:
10        if count[char] == 1:
11            return char
12    return None
13
14# Example usage
15input_string = input("Enter a string: ")
16result = first_non_repeating_char(input_string)
17print("First non-repeating character:", result)

挑戰 3 觀察:

  • GPT 5 速度:反應速度非常快,幾乎即時完成。
  • GPT 5 代碼:提供的短代碼沒有入口點,也沒有註解。範例用法存在錯誤。
  • Grok 4 速度:反應速度較慢,「思考」時間稍長(約 8 秒)。
  • Grok 4 代碼:提供的短代碼沒有入口點,但帶有簡短的文檔字串。

Python 挑戰 4 - API 集成

挑戰 4 提示:

使用請求庫從公共 API 獲取當前比特幣的美元價格並列印出來。

挑戰 4 GPT 5 代碼:

 1import requests
 2
 3def get_bitcoin_price_usd():
 4    url = "https://api.coindesk.com/v1/bpi/currentprice/USD.json"
 5    try:
 6        response = requests.get(url, timeout=5)
 7        response.raise_for_status()  # Raise HTTPError for bad responses
 8        data = response.json()
 9        price = data["bpi"]["USD"]["rate"]
10        print(f"Current Bitcoin Price: ${price} USD")
11    except requests.exceptions.RequestException as e:
12        print(f"Error fetching Bitcoin price: {e}")
13    except (KeyError, ValueError) as e:
14        print(f"Error parsing response: {e}")
15
16if __name__ == "__main__":
17    get_bitcoin_price_usd()

挑戰 4 Grok 4 代碼:

 1import requests
 2
 3# Define the API endpoint
 4url = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd"
 5
 6# Fetch the data
 7response = requests.get(url)
 8
 9# Check if the request was successful
10if response.status_code == 200:
11    data = response.json()
12    bitcoin_price = data['bitcoin']['usd']
13    print(f"Current Bitcoin price in USD: ${bitcoin_price}")
14else:
15    print(f"Error fetching data: {response.status_code}")

挑戰 4 觀察:

  • GPT 5 速度:反應速度非常快,幾乎是即時的。
  • GPT 5 代碼:提供簡短優雅的代碼,包含入口點,但沒有註釋。
  • Grok 4 速度:反應速度較慢,「思考」起來稍長一些(約 23 秒)。
  • Grok 4 代碼:提供的代碼略短,沒有入口點,但包含註釋。

Python 挑戰 5 - 網頁抓取

挑戰 5 提示:

使用請求和 BeautifulSoup 從 https://news.ycombinator.com/ 抓取排名前 5 的新聞標題並列印出來。

挑戰 5 GPT 5 代碼:

 1import requests
 2from bs4 import BeautifulSoup
 3
 4def get_top_hn_headlines(limit=5):
 5    url = "https://news.ycombinator.com/"
 6    try:
 7        response = requests.get(url, timeout=5)
 8        response.raise_for_status()
 9        
10        soup = BeautifulSoup(response.text, "html.parser")
11        headlines = [a.get_text() for a in soup.select(".titleline > a")]
12        
13        print(f"Top {limit} Hacker News Headlines:")
14        for i, title in enumerate(headlines[:limit], 1):
15            print(f"{i}. {title}")
16    except requests.exceptions.RequestException as e:
17        print(f"Error fetching Hacker News: {e}")
18
19if __name__ == "__main__":
20    get_top_hn_headlines()

挑戰 5 Grok 4 代碼:

 1import requests
 2from bs4 import BeautifulSoup
 3
 4# Define the URL
 5url = 'https://news.ycombinator.com/'
 6
 7# Fetch the webpage
 8response = requests.get(url)
 9response.raise_for_status()  # Raise an error for bad status codes
10
11# Parse the HTML content
12soup = BeautifulSoup(response.text, 'html.parser')
13
14# Find the top 5 story elements
15stories = soup.find_all('tr', class_='athing')[:5]
16
17# Print the top 5 headlines
18print("Top 5 News Headlines from Hacker News:")
19for i, story in enumerate(stories, 1):
20    title_span = story.find('span', class_='titleline')
21    if title_span:
22        headline = title_span.find('a').text
23        print(f"{i}. {headline}")

挑戰 5 觀察:

  • GPT 5 速度:反應速度非常快,幾乎是即時的。
  • GPT 5 代碼:提供簡短優雅的代碼,包含入口點,但沒有註釋。
  • Grok 4 速度:反應速度較慢,「感覺」稍長一些(約 13 秒)。
  • Grok 4 代碼:提供稍長的代碼,沒有入口點,但包含註釋。

Python 挑戰 6 - 檔案壓縮

挑戰 6 提示:

建立一個 Python 腳本,將目前目錄中的所有 .txt 檔案壓縮到「archive.zip」檔案中。

挑戰 6 GPT 5 代碼:

 1import zipfile
 2import glob
 3import os
 4
 5def zip_text_files(output_zip="archive.zip"):
 6    txt_files = glob.glob("*.txt")
 7    if not txt_files:
 8        print("No .txt files found in the current directory.")
 9        return
10    
11    with zipfile.ZipFile(output_zip, "w") as zipf:
12        for file in txt_files:
13            zipf.write(file, os.path.basename(file))
14            print(f"Added: {file}")
15    
16    print(f"Created {output_zip} containing {len(txt_files)} files.")
17
18if __name__ == "__main__":
19    zip_text_files()

挑戰 6 Grok 4 代碼:

 1import os
 2from zipfile import ZipFile
 3
 4# Get the current directory
 5current_dir = os.getcwd()
 6
 7# List all .txt files in the current directory
 8txt_files = [f for f in os.listdir(current_dir) if f.endswith('.txt')]
 9
10# Create a zip file and add the .txt files
11with ZipFile('archive.zip', 'w') as zipf:
12    for file in txt_files:
13        zipf.write(file)
14
15print(f"Successfully zipped {len(txt_files)} .txt files into 'archive.zip'.")

挑戰 6 觀察:

  • GPT 5 速度:反應速度非常快,幾乎即時完成。
  • GPT 5 代碼:提供簡短優雅的代碼,包含入口點,但沒有註釋。
  • Grok 4 速度:反應速度較慢,「思考」時間稍長(約 10 秒)。
  • Grok 4 代碼:提供簡短的代碼,沒有入口點,但包含註釋。

Python 挑戰 7 - 影像處理

挑戰 7 提示:

使用 Pillow (PIL) 將目前目錄中的所有 JPEG 影像調整為 800x600 像素,並將其儲存到「輸出」資料夾。

挑戰 7 GPT 5 代碼:

 1import os
 2from PIL import Image
 3import glob
 4
 5def resize_jpeg_images(width=800, height=600, output_dir="output"):
 6    # Create output folder if it doesn't exist
 7    os.makedirs(output_dir, exist_ok=True)
 8
 9    # Find all .jpg and .jpeg files (case-insensitive)
10    jpeg_files = glob.glob("*.jpg") + glob.glob("*.jpeg") + glob.glob("*.JPG") + glob.glob("*.JPEG")
11
12    if not jpeg_files:
13        print("No JPEG images found in the current directory.")
14        return
15
16    for file in jpeg_files:
17        try:
18            with Image.open(file) as img:
19                img_resized = img.resize((width, height), Image.LANCZOS)
20                output_path = os.path.join(output_dir, os.path.basename(file))
21                img_resized.save(output_path, "JPEG")
22                print(f"Resized and saved: {output_path}")
23        except Exception as e:
24            print(f"Error processing {file}: {e}")
25
26if __name__ == "__main__":
27    resize_jpeg_images()

挑戰 7 Grok 4 代碼:

 1import os
 2from PIL import Image
 3
 4# Get the current directory
 5current_dir = os.getcwd()
 6
 7# Create the output folder if it doesn't exist
 8output_folder = os.path.join(current_dir, 'output')
 9os.makedirs(output_folder, exist_ok=True)
10
11# List all JPEG files in the current directory (case-insensitive)
12jpeg_files = [f for f in os.listdir(current_dir) 
13              if f.lower().endswith(('.jpg', '.jpeg'))]
14
15# Resize each image and save to output folder
16resized_count = 0
17for file in jpeg_files:
18    try:
19        img_path = os.path.join(current_dir, file)
20        img = Image.open(img_path)
21        resized_img = img.resize((800, 600))
22        output_path = os.path.join(output_folder, file)
23        resized_img.save(output_path)
24        resized_count += 1
25    except Exception as e:
26        print(f"Error processing {file}: {e}")
27
28print(f"Successfully resized and saved {resized_count} JPEG images to the 'output' folder.")

挑戰 7 觀察:

  • GPT 5 速度:反應速度非常快,幾乎是即時的。
  • GPT 5 代碼:提供簡短優雅的代碼,包含入口點和註釋。
  • Grok 4 速度:反應速度較慢,「思考」起來稍長一些(約 10 秒)。
  • Grok 4 代碼:提供稍長的代碼,沒有入口點,但包含註釋。

Python 挑戰 8 - 多執行緒

挑戰 8 提示:

建立一個 Python 腳本,使用執行緒技術從給定的 URL 同時下載 5 個不同的檔案。

挑戰 8 GPT 5 代碼:

 1import os
 2from pathlib import Path
 3from urllib.parse import urlparse
 4from concurrent.futures import ThreadPoolExecutor, as_completed
 5
 6import requests
 7
 8CHUNK_SIZE = 1024 * 64  # 64KB
 9
10
11def unique_path(dest_dir: Path, filename: str) -> Path:
12    """Return a unique path inside dest_dir by appending (1), (2), ... if needed."""
13    dest = dest_dir / filename
14    if not dest.exists():
15        return dest
16    stem, suffix = os.path.splitext(filename)
17    i = 1
18    while True:
19        candidate = dest_dir / f"{stem} ({i}){suffix}"
20        if not candidate.exists():
21            return candidate
22        i += 1
23
24
25def filename_from_url(url: str, index: int) -> str:
26    """Get a safe filename from URL; fall back to file_{index} if missing."""
27    path = urlparse(url).path
28    name = os.path.basename(path).strip()
29    return name or f"file_{index}"
30
31
32def download_file(url: str, dest_dir: Path, index: int, timeout: int = 15) -> Path:
33    """Download a single file to dest_dir. Returns the saved path."""
34    dest_dir.mkdir(parents=True, exist_ok=True)
35    base_name = filename_from_url(url, index)
36    dest_path = unique_path(dest_dir, base_name)
37
38    headers = {"User-Agent": "python-threaded-downloader/1.0"}
39    with requests.get(url, stream=True, timeout=timeout, headers=headers) as r:
40        r.raise_for_status()
41        with open(dest_path, "wb") as f:
42            for chunk in r.iter_content(chunk_size=CHUNK_SIZE):
43                if chunk:  # filter out keep-alive chunks
44                    f.write(chunk)
45    return dest_path
46
47
48def download_concurrently(urls, out_dir="downloads", max_workers=5):
49    """Download given URLs concurrently using threads."""
50    dest_dir = Path(out_dir)
51    results = []
52    errors = []
53
54    with ThreadPoolExecutor(max_workers=max_workers) as executor:
55        future_to_url = {
56            executor.submit(download_file, url, dest_dir, i): url
57            for i, url in enumerate(urls, start=1)
58        }
59        for future in as_completed(future_to_url):
60            url = future_to_url[future]
61            try:
62                saved_path = future.result()
63                print(f"✅ Downloaded: {url} -> {saved_path}")
64                results.append(saved_path)
65            except Exception as e:
66                print(f"❌ Failed: {url} ({e})")
67                errors.append((url, e))
68    print(f"\nDone. {len(results)} succeeded, {len(errors)} failed.")
69    return results, errors
70
71
72if __name__ == "__main__":
73    # Replace these with your 5 URLs
74    urls = [
75        "https://example.com/file1.jpg",
76        "https://example.com/file2.pdf",
77        "https://example.com/file3.zip",
78        "https://example.com/file4.png",
79        "https://example.com/file5.mp4",
80    ]
81    download_concurrently(urls, out_dir="downloads", max_workers=5)

挑戰 8 Grok 4 代碼:

 1import threading
 2import urllib.request
 3
 4def download_file(url, filename):
 5    """
 6    Downloads a file from the given URL and saves it with the specified filename.
 7    """
 8    try:
 9        urllib.request.urlretrieve(url, filename)
10        print(f"Downloaded {filename} from {url}")
11    except Exception as e:
12        print(f"Error downloading {url}: {e}")
13
14# List of 5 example URLs (replace with your actual URLs)
15urls = [
16    "https://www.example.com/file1.txt",
17    "https://www.example.com/file2.pdf",
18    "https://www.example.com/file3.jpg",
19    "https://www.example.com/file4.zip",
20    "https://www.example.com/file5.docx"
21]
22
23# Corresponding filenames to save the downloads
24filenames = [
25    "file1.txt",
26    "file2.pdf",
27    "file3.jpg",
28    "file4.zip",
29    "file5.docx"
30]
31
32# Create and start threads for concurrent downloads
33threads = []
34for url, filename in zip(urls, filenames):
35    thread = threading.Thread(target=download_file, args=(url, filename))
36    thread.start()
37    threads.append(thread)
38
39# Wait for all threads to complete
40for thread in threads:
41    thread.join()
42
43print("All downloads completed.")

挑戰 8 觀察:

  • GPT 5 速度:反應速度較慢,「思考」時間稍長(約 10 秒)。
  • GPT 5 代碼:提供包含入口點和註釋的長而優雅的代碼。
  • Grok 4 速度:反應速度較慢,「思考」時間稍長(約 21 秒)。
  • Grok 4 代碼:提供較短的代碼,不包含入口點,但包含註解。

Python 挑戰 9 - 資料庫交互

挑戰 9 提示:

連接到 SQLite 資料庫,建立「users」表,插入範例數據,並查詢所有使用者。

挑戰 9 GPT 5 代碼:

 1import sqlite3
 2
 3def main():
 4    # Connect to (or create) the database
 5    conn = sqlite3.connect("example.db")
 6    cursor = conn.cursor()
 7
 8    # Create the users table if it doesn't exist
 9    cursor.execute("""
10        CREATE TABLE IF NOT EXISTS users (
11            id INTEGER PRIMARY KEY AUTOINCREMENT,
12            name TEXT NOT NULL,
13            email TEXT UNIQUE NOT NULL
14        )
15    """)
16
17    # Insert sample data
18    sample_users = [
19        ("Alice", "[email protected]"),
20        ("Bob", "[email protected]"),
21        ("Charlie", "[email protected]"),
22    ]
23
24    try:
25        cursor.executemany("INSERT INTO users (name, email) VALUES (?, ?)", sample_users)
26    except sqlite3.IntegrityError:
27        # Ignore duplicates if run multiple times
28        pass
29
30    # Commit changes
31    conn.commit()
32
33    # Query all users
34    cursor.execute("SELECT id, name, email FROM users")
35    users = cursor.fetchall()
36
37    print("Users in database:")
38    for user in users:
39        print(user)
40
41    # Close the connection
42    conn.close()
43
44if __name__ == "__main__":
45    main()

挑戰 9 Grok 4 代碼:

 1import sqlite3
 2
 3# Connect to an in-memory SQLite database
 4conn = sqlite3.connect(':memory:')
 5cursor = conn.cursor()
 6
 7# Create the 'users' table
 8cursor.execute('''
 9    CREATE TABLE users (
10        id INTEGER PRIMARY KEY,
11        name TEXT,
12        age INTEGER
13    )
14''')
15
16# Insert sample data
17cursor.execute("INSERT INTO users (name, age) VALUES ('Alice', 30)")
18cursor.execute("INSERT INTO users (name, age) VALUES ('Bob', 25)")
19cursor.execute("INSERT INTO users (name, age) VALUES ('Charlie', 35)")
20
21# Commit the changes
22conn.commit()
23
24# Query all users
25cursor.execute("SELECT * FROM users")
26results = cursor.fetchall()
27
28# Print the results
29print("ID | Name | Age")
30print("----------------")
31for row in results:
32    print(f"{row[0]} | {row[1]} | {row[2]}")
33
34# Close the connection
35conn.close()

挑戰 9 觀察:

  • GPT 5 速度:反應速度非常快,幾乎是即時的。即使我們只是直截了當地說“連接…”而不是“寫入或創建”,我們也理解需要腳本。
  • GPT 5 代碼:提供了長而優雅的代碼,包含入口點和註釋。
  • Grok 4 速度:反應速度較慢,「思考」時間稍長(約 16 秒)。
  • Grok 4 代碼:提供了略短的代碼,並且首次提供了入口點和註釋。有趣的是,有些函數/測試名稱與 ChatGPT 5 的風格相似。

Python 挑戰 10 - 單元測試

挑戰 10 提示:

寫一個 Python 單元測試,驗證函數「is_prime(n)」是否正確辨識質數。

挑戰 10 GPT 5 代碼:

 1import unittest
 2
 3# Example implementation of is_prime for testing purposes
 4# If you already have this function, you can remove this definition.
 5def is_prime(n):
 6    """Return True if n is a prime number, else False."""
 7    if n <= 1:
 8        return False
 9    if n <= 3:
10        return True
11    if n % 2 == 0 or n % 3 == 0:
12        return False
13    i = 5
14    while i * i <= n:
15        if n % i == 0 or n % (i + 2) == 0:
16            return False
17        i += 6
18    return True
19
20
21class TestIsPrime(unittest.TestCase):
22    def test_primes(self):
23        primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
24        for p in primes:
25            with self.subTest(p=p):
26                self.assertTrue(is_prime(p), f"{p} should be prime")
27
28    def test_non_primes(self):
29        non_primes = [0, 1, 4, 6, 8, 9, 10, 12, 15, 20, 25]
30        for n in non_primes:
31            with self.subTest(n=n):
32                self.assertFalse(is_prime(n), f"{n} should not be prime")
33
34if __name__ == "__main__":
35    unittest.main()

挑戰 10 Grok 4 代碼:

 1import unittest
 2
 3# Assuming the is_prime function is defined in a module named prime_checker
 4# Replace 'prime_checker' with the actual module name where is_prime is defined
 5from prime_checker import is_prime
 6
 7class TestIsPrime(unittest.TestCase):
 8    def test_prime_numbers(self):
 9        """Test that prime numbers are correctly identified."""
10        primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
11        for num in primes:
12            with self.subTest(num=num):
13                self.assertTrue(is_prime(num), f"{num} should be prime")
14
15    def test_non_prime_numbers(self):
16        """Test that non-prime numbers are correctly identified."""
17        non_primes = [0, 1, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, 27, 28]
18        for num in non_primes:
19            with self.subTest(num=num):
20                self.assertFalse(is_prime(num), f"{num} should not be prime")
21
22    def test_negative_numbers(self):
23        """Test that negative numbers are not considered prime."""
24        negatives = [-1, -2, -3, -5, -7]
25        for num in negatives:
26            with self.subTest(num=num):
27                self.assertFalse(is_prime(num), f"{num} should not be prime")
28
29    def test_one_and_zero(self):
30        """Explicitly test 0 and 1, which are not prime."""
31        self.assertFalse(is_prime(0))
32        self.assertFalse(is_prime(1))
33
34if __name__ == '__main__':
35    unittest.main()

挑戰 10 的觀察結果

  • GPT 5 速度:反應速度非常快,幾乎是即時的。
  • GPT 5 代碼:提供長而優雅的代碼,包含入口點和註釋。
  • Grok 4 速度:反應速度較慢,「思考」時間稍長(約 12 秒)。
  • Grok 4 代碼:提供的代碼略短,並且首次包含入口點和註釋。有趣的是,函數名稱與 ChatGPT 5 相同。

評估標準

我們將根據以下標準對每個 AI 進行評分:

  • 程式碼正確性:無需進行重大修改即可運行嗎?
  • 可讀性:程式碼是否簡潔且註解清晰?
  • 效率:是否使用了最佳方法?
  • 錯誤處理:是否能夠預測可能的故障?
  • 可解釋性:是否提供了清晰的推理?

初步觀察

根據以往和現在的經驗:

  • ChatGPT 5 傾向於提供更冗長、文件更完善的程式碼,速度也更快。
  • Grok 4 更傾向於極簡主義,反應速度較慢,有時會省略註釋。

兩者都擅長標準任務,但 Grok 在處理多步驟推理提示時可能會遇到困難。

10 項挑戰的突出之處

  • 提示執行情況:GPT-5 始終專注於任務(例如,BTC API)。 Grok 4 偶爾會出現偏差(挑戰 4)。
  • 入口點和結構:GPT-5 始終使用入口點和輔助函數;Grok 4 經常編寫沒有入口點的單一檔案腳本。
  • 錯誤處理:GPT-5 更頻繁地添加超時/raise_for_status/try-except;Grok 4 則傾向於極簡主義。
  • 依賴關係與假設:GPT-5 盡可能使用 stdlib;Grok 4 則依賴 Pandas 或更簡單的 urllib 預設函式庫。
  • 資料模型假設:GPT-5 推斷欄位和計算值(數量 × 價格);Grok 4 假設列已預先聚合。
  • 演算法謹慎:兩者都解決了邏輯任務;GPT-5 的範例存在一個小的變數錯誤,而 Grok 4 的 HN 範例存在語法錯誤。
  • 效能態勢:GPT-5 使用串流 + 執行緒池進行下載;Grok 4 使用原始執行緒 + urlretrieve(更簡單,但穩健性較差)。

結論

雖然這兩種工具都可以編寫函數式 Python 程式碼,但最終選擇可能取決於開發者的偏好

  • 如果您注重詳細的解釋循序漸進的推理快速的程式碼產生豐富的註解,請選擇ChatGPT 5
  • 如果您喜歡簡潔簡單的程式碼,盡量減少冗餘程式碼,並且程式碼產生速度較慢,請選擇Grok 4

說實話,我更喜歡ChatGPT 5,因為它的反應速度更快,並且能夠產生更好、更詳細的Python程式碼。抱歉了,伊隆馬斯克。

常見問題 (FAQ)

**OpenAI ChatGPT 5 和 Grok 4 哪個比較適合初學者? ** ChatGPT 5。它解釋得更詳細,包含更安全的預設值(逾時、錯誤處理),結構更簡潔。

**在這些測試中,哪個產生的程式碼問題更少? ** ChatGPT 5 整體而言。 Grok 4 在抓取資料時偶爾會出現提示漂移和輕微的語法錯誤。

**哪個比較快? ** 在您的運行中,ChatGPT 5 的平均反應速度更快。您的計時已包含在每次挑戰中。

**我需要檢查它們產生的程式碼嗎? ** 是的。兩種模型都可能犯一些小錯誤;請務必執行測試並為 I/O 和網路程式碼添加防護措施。

**哪個處理檔案、影像和網路比較穩健? ** ChatGPT 5。它傾向於添加入口點、超時、串流和更好的影像重採樣。

**Grok 4 有什麼優勢嗎? ** 是的,當您已經了解上下文並希望最小化輸出時,Grok 4 的腳本更簡潔、更快捷。

**哪種提示樣式效果最好? ** 明確說明輸入/輸出、函式庫和邊緣情況(例如:「使用帶逾時的請求,列印 JSON 解析錯誤」)。

**我可以依賴這兩種模型來寫生產程式碼嗎? ** 將它們用作加速器,而不是替代方案:將測試、linting 和安全審查保留在您的流程中。