4

以下を使用して、同じクラスのメソッド内でクラス変数 (辞書) にアクセスするときに、パフォーマンスに違いがあるかどうか疑問に思います。

self.class_variable_dict.add(some_key, some_value)

ClassName.class_variable_dict.add(some_key, some_value)

明らかに、同じ名前のインスタンス変数がない限り、どちらも機能しますが、どちらか一方を優先する必要がある理由/ユースケースはありますか?

4

3 に答える 3

6

経由でアクセスする場合は、最初にインスタンスの名前空間を確認する必要があるため、経由ClassNameではなく経由でアクセスする方selfわずかに高速です。selfしかし、それが重要であることを示唆するプロファイリング情報がない限り、違いがまったく重要であるとは思いません。

したがって、人間として読みやすく/理解しやすいと思われる方を使用することをお勧めします。

意味的には、class_variable_dict変数がどこかで隠されている場合にのみ、それらは異なります。特に、(a)self同じ名前の変数を定義している場合。または (b)selfが のサブクラスのインスタンスでありClassName、そのサブクラス (または のサブクラスであるそのベースの 1 つClassName) が同じ名前の変数を定義している。どちらも当てはまらない場合は、意味的に同一である必要があります。

編集:

delnamには良い点があります。いずれかを高速化する要因があります。非常にタイトなループでない限り、違いは些細なものであるという私の主張を支持します。それをテストするために、考えられる限り最もタイトなループを作成し、timeit. 結果は次のとおりです。

  • クラス変数経由のアクセス: 20.226 秒
  • inst var 経由のアクセス: 23.121 秒

数回の実行に基づくと、エラー バーは約 1 秒のように見えます。つまり、これは統計的に有意な差ですが、おそらく心配する必要はありません。ここに私のテストコードがあります:

import timeit

setup='''
class A:
    var = {}
    def f1(self):
        x = A.var
    def f2(self):
        x = self.var

a = A()
'''
print 'access via class var: %.3f' % timeit.timeit('a.f1()', setup=setup, number=100000000)
print 'access via inst var: %.3f' % timeit.timeit('a.f2()', setup=setup, number=100000000)
于 2012-05-22T14:08:29.697 に答える
3

さまざまなオプションがすべて何をするかを見てみましょう。

In [1]: class Foo:
   ...:     bar = {}
   ...:     

In [2]: import dis
In [3]: dis.dis(lambda: Foo.bar.add(1,2))
  1           0 LOAD_GLOBAL              0 (Foo) 
              3 LOAD_ATTR                1 (bar) 
              6 LOAD_ATTR                2 (add) 
              9 LOAD_CONST               1 (1) 
             12 LOAD_CONST               2 (2) 
             15 CALL_FUNCTION            2 
             18 RETURN_VALUE         

In [4]: dis.dis(lambda: Foo().bar.add(1,2))
  1           0 LOAD_GLOBAL              0 (Foo) 
              3 CALL_FUNCTION            0 
              6 LOAD_ATTR                1 (bar) 
              9 LOAD_ATTR                2 (add) 
             12 LOAD_CONST               1 (1) 
             15 LOAD_CONST               2 (2) 
             18 CALL_FUNCTION            2 
             21 RETURN_VALUE 

ご覧のとおり、どちらのスタイルも、2 番目のケースでのオブジェクトの作成を除けば、同じバイトコードを生成します。


これに対するもう1つの側面は、それが問題ではないということです。最も正確な方法であなたの目的を表現するものは何でも使用してください。速度が重要な場合にのみ最適化してください。

一緒に行くことをお勧めしますClassName.dict_value[key] = value

于 2012-05-22T14:11:05.757 に答える