3

スクリプトを実行するたびに10000回以上実行することを計画しているPythonで関数を作成しています。この関数には現在3つのサブ関数が含まれていますが、スクリプトが完了すると20以上のサブ関数が含まれる可能性があります。ちょっと思ったんです; これらの関数を何度も宣言すると(親関数は何千回も実行されるため)、パフォーマンスコストが繰り返し発生しますか、それとも最適化されており、問題はありませんか?

これらすべてのサブ機能をクラスに分離すると、パフォーマンスが向上しますか?

(私はこれをテストし、頭のてっぺんに答えがわからない場合はここに結果を投稿するつもりです。)

4

2 に答える 2

8

関数定義によるパフォーマンスへの影響はごくわずかであり、ローカル変数の定義に匹敵します。

関数の本体は1回だけコンパイルされ、コードブロックの実行中にコンパイルされたブロック(LOAD_CONST)をロードするだけで、バイトコードの結果がMAKE FUNCTIONローカル変数に格納されます。

>>> import dis
>>> def foo():
...     def bar():
...         pass
...     print 'boo!'
... 
>>> dis.dis(foo)
  2           0 LOAD_CONST               1 (<code object bar at 0x106c447b0, file "<stdin>", line 2>)
              3 MAKE_FUNCTION            0
              6 STORE_FAST               0 (bar)

  4           9 LOAD_CONST               2 ('boo!')
             12 PRINT_ITEM          
             13 PRINT_NEWLINE       
             14 LOAD_CONST               0 (None)
             17 RETURN_VALUE        

ここで、ネストされた関数を含む関数を何千回も呼び出すと、そのMAKE_FUNCTION操作のパフォーマンスへの影響に気付くでしょう。

>>> import timeit
>>> def nonlocal(): pass
... 
>>> def callnonlocal(): nonlocal()
... 
>>> def calllocal():
...     def localf(): pass
...     localf()
... 
>>> timeit.timeit('callnonlocal()', 'from __main__ import callnonlocal')
0.39106082916259766
>>> timeit.timeit('calllocal()', 'from __main__ import calllocal')
0.4878239631652832

ただし、関数に実際のコードを入れるほど、その差は小さくなることに注意してください。MAKE_FUNCTION上記の例は非常に工夫されており、実行時間に対するバイトコードの影響のみに焦点を当てています。

まず、読みやすさと保守性を最適化します。

于 2012-09-14T20:52:49.720 に答える
0

はい、別の関数内で関数を定義すると、モジュールスコープで関数を定義するよりもパフォーマンスがわずかに低下します。

于 2012-09-14T20:53:30.680 に答える