LoginSignup
2
2

More than 1 year has passed since last update.

ChatGPTがEffective Pythonのプログラムを書けるか試してみた

Posted at

はじめに

ChatGPTはプログラミングに関して高い能力を発揮しているそうなので、自分もテストしてみました。

今回取り扱う書籍は以下のEffective Pythonです。

Effective PythonはPython中級者から上級者が対象の書籍で、使いやすく理解しやすいテクニック(一部はかなりマニアック)が紹介されています。

この記事はChatGPTに敬意を示しつつも、今回は効率の良い実用的なPythonのプログラムを書くことができるかどうかを調べる目的で作成しています。

少しでも参考になれば幸いです!

関数のプログラム

2変数徐算する関数(項目20)

まず2変数を徐算する関数の作成を指示したら以下の関数が出力されました。

def divide_numbers(num1, num2):
    return num1 / num2

この関数は、num2=0の時にエラーを吐くので例外処理が必須ですが、ChatGPTはdefaultで例外処理を書いてくれませんでした。

次に例外処理を書くように指示した時の関数は以下です。

def divide_numbers(num1, num2):
    try:
        result = num1 / num2
    except ZeroDivisionError:
        print("Error: Cannot divide by zero.")
        return None
    return result

しっかり例外処理が記述されています。

ですがEffective Pythonでは上記のNoneを返すプログラムよりも例外を送出する関数が推奨されています。

def divide_numbers(num1, num2):
    try:
        return num1 / num2
    except ZeroDivisionError:
        raise ValueError('Cannot divide by zero')

ラッパー関数の作成(項目26)

プログラムの実行時間を計測するラッパー関数を作成するように指示したら以下のように出力されました。

import time

def measure_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Execution time of '{func.__name__}': {(end_time - start_time):.6f} seconds")
        return result
    return wrapper

内容は大正解なのですが、Effective Pythonではfunctools.wrapsを用いることが推奨されています。

import time
from functools import wraps

def measure_time(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Execution time of '{func.__name__}': {(end_time - start_time):.6f} seconds")
        return result
    return wrapper

詳しくはこちらで解説しています。

頑健性と性能

性能確認のプログラム(項目70)

pythonのプログラムがしばしば想定外の振る舞いを引き起こすことがあります。(早いと想定したプログラムが異常に遅いなど)

このようなケースでは、プログラムを最適化する前にプログラム自体の性能を測ることが重要です。

例えば以下のような関数の性能を調査します。

def insert_sort(data):
    result = []
    for v in data:
        insert_value(result, v)
    return result

def insert_value(array, v):
    for i,existing in enumerate(array):
        if existing > v:
            array.insert(i,v)
            return
    array.append(v)

Effective Python模範回答は以下のようにcProfileを用いて性能を評価します。(プロファイルする)

from random import randint
from cProfile import Profile

data = [randint(0,10**4) for _ range (10**4)]
test = lambda: insert_sort(data)

profile = Profile()
profile.runcall(test)

stas = Stas(profile)
stats.strip_dirs()
stas.print_stats()

ChatGPTには、「具体的な一つ一つの処理の性能を調査」、または「プログラムを最適化する前にプログラム自体の性能を調査」を指示をします。

その結果は以下です。

import time
import random

def measure_performance(func, data):
    start_time = time.time()
    result = func(data)
    end_time = time.time()
    return end_time - start_time, result

data_sizes = [10, 100, 1000, 10000]

for size in data_sizes:
    data = list(range(size))
    random.shuffle(data)
    time_taken, result = measure_performance(insert_sort, data)
    print(f"Data size: {size} - Time taken: {time_taken:.5f} seconds")

data_sizeでバリエーションを豊富にしてくれましたが、肝心の性能は実行時間を計測する関数で評価する仕様のようです。

ですが、今回意図しているようなプログラムの性能を詳しくは評価できません。

次にChatGPTにプロファイルをしてください、と専門用語を加えて指示しました。
結果は以下です。

import cProfile

data_sizes = [10, 100, 1000, 10000]

for size in data_sizes:
    data = list(range(size))
    random.shuffle(data)

    # プロファイルの開始
    pr = cProfile.Profile()
    pr.enable()
    insert_sort(data)
    pr.disable()

    # プロファイリング結果の出力
    print(f"Data size: {size}")
    pr.print_stats(sort="cumulative")

バッチリです!!

プログラムの性能を測ると指示するよりも、プロファイルといった専門知識を投げかけることが必要でした。

まとめ

ChatGPTは要件に合わせてプログラムを書くことができます。

一方で、ChatGPTの作成したプログラムが最適でないケースも多く見受けれると予想されます。

最適なプログラムを書くためには、まだ我々には、専門的な知識が必要になるでしょう。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2