2012-03-20 53 views
10

以下の例は、Python 2.7のRESTデータベースドライバからのものです。以下__setattr__方法でgetattr()がselfよりもずっと遅いのはなぜですか?__ dict __。get()?

は、私がコメントアウトgetattr()ラインを使用している場合、それは230

に600のRPSからオブジェクトのインスタンス化のパフォーマンスが低下し、なぜこの場合self.__dict__.get()よりgetattr()そんなに遅いですか?要するに

class Element(object): 

    def __init__(self, client): 
     self._client = client 
     self._data = {} 
     self._initialized = True 

    def __setattr__(self, key, value): 
     #_initialized = getattr(self, "_initialized", False) 
     _initialized = self.__dict__.get("_initialized", False) 
     if key in self.__dict__ or _initialized is False: 
      # set the attribute normally 
      object.__setattr__(self, key, value) 
     else: 
      # set the attribute as a data property 
      self._data[key] = value 
+1

このようなパフォーマンスの違いがある場合は、ローカル変数に 'self .__ dict__'をキャッシュしてください(2回しかアクセスできない場合)。 ( '__setattr__'の始めに' dict_ = self .__ dict__') – jsbueno

答えて

12

:ちょうど(スタートのために、getattrは右__dict__を選択することがありますが、もっと上に行く全体の多くがあります)__dict__プロパティにアクセスすると同じものではないとする、getattr(foo,bar)does the same thing as foo.barので。

詳細はこちら、またはhttp://docs.python.org/reference/datamodel.html( "getattr"で検索)にリンクされています。

+2

@bereal:あなたは物事を再び読む必要があります。 foo .__ dict __。get()に必要な操作は、getattr()の適切なサブセットです。 – bukzor

+2

@bereal Pythonバイトコードはプリミティブ操作に対応していないことに注意してください。非常に複雑な関数を呼び出すためには非常に少量のバイトコードを持つことができますが、シンプルな式では多くのバイトコードを生成できます。また、bukzorが言ったことは、正確で適切なものです。 – Marcin

+0

@berealこれは、 'getattr(foo、 '__ dict __')'を効率的に呼び出すことができるため、 'foo .__ dict__'は' getattr(foo、 '__dict __') 'と同じことをすることは決してありません任意の属性の逆参照よりも優先されます。 – Marcin

関連する問題