名前解決がパフォーマンスに与える影響
http://blog.miraclelinux.com/asianpen/2008/05/python-code-rea.html#more
でも実験されていますが、もう少し細かいケースで試してみました。
scope_test.py
def with_local(num): l = [] l_value = True for i in xrange(num): l.append(l_value) def with_nested(num): l = [] n_value = True def nested(num): for i in xrange(num): l.append(n_value) nested(num) m_value = True def with_module(num): l = [] for i in xrange(num): l.append(m_value) def with_builtin(num): l = [] for i in xrange(num): l.append(True) if __name__ == "__main__": import sys from timeit import Timer t = sys.argv[1] num = sys.argv[2] if t == "local": def_name = "with_local" elif t == "nested": def_name = "with_nested" elif t == "module": def_name = "with_module" elif t == "builtin": def_name = "with_builtin" t = Timer("%s(%s)" % (def_name, num), "from __main__ import %s" % def_name) print def_name, t.timeit(1)
手元のcoLinux(on ThinkPadX61 Core2 Duo 2GHz)で実行。まずは100万回。
[michisu@colinux] $ python scope_test.py local 1000000 [~/python-code-reading] with_local 0.941817998886 [michisu@colinux] $ python scope_test.py nested 1000000 [~/python-code-reading] with_nested 1.04100513458 [michisu@colinux] $ python scope_test.py module 1000000 [~/python-code-reading] with_module 1.03532505035 [michisu@colinux] $ python scope_test.py builtin 1000000 [~/python-code-reading] with_builtin 1.08331394196
1000万回。
[michisu@colinux] $ python scope_test.py local 10000000 [~/python-code-reading] with_local 9.48914504051 [michisu@colinux] $ python scope_test.py nested 10000000 [~/python-code-reading] with_nested 10.4752728939 [michisu@colinux] $ python scope_test.py module 10000000 [~/python-code-reading] with_module 10.4114220142 [michisu@colinux] $ python scope_test.py builtin 10000000 [~/python-code-reading] with_builtin 10.6834070683
ビルトイン型をそのまま使うとやはり少し遅い。
1000万回回しても1秒程度しか差が出ないので、Setのような汎用コレクションクラスのコードでもない限り、普段は気にしなくても良さそうだけど。(これをつねにやるぐらいならCを使えって話になる)
ある名前がコードブロック内で使われると、その名前を最も近傍から囲うようなスコープ (最内スコープ: nearest enclosing scope) を使って束縛の解決を行います。
http://www.python.jp/doc/2.4/ref/naming.html
ということで、最内スコープによる名前の解決がもっとも高速になり、順次外のスコープが使われるのでルックアップが遅くなると思われます。
上のケースではnestedがmoduleより常に少しだけ遅いのが面白いですが、この理由はよく分かりません。
追記。タイトル変更しました。「スコープの変数解決が」→「名前解決が」
追記2。地の文で回数の桁が間違ってたので直しました。