2012-09-13 24 views
8

もっと複雑な問題に取り組もうとしているうちに、ローカル変数とメンバー変数のアクセス速度を比較しました。ここでは、テストプログラム ローカル変数アクセスがPythonのクラスメンバーアクセスよりも速いのはなぜですか?

#!/usr/bin/env python 

MAX=40000000 

class StressTestMember(object): 
    def __init__(self): 
     self.m = 0 

    def do_work(self): 
     self.m += 1 
     self.m *= 2 

class StressTestLocal(object): 
    def __init__(self): 
     pass 

    def do_work(self): 
     m = 0 
     m += 1 
     m *= 2 

# LOCAL access test 
for i in range(MAX): 
    StressTestLocal().do_work() 

# MEMBER access test 
for i in range(MAX): 
    StressTestMember().do_work() 

は、私はそれが各イテレーションのStressTestMemberStressTestLocalをインスタンス化するためには悪いアイデアのように見えるかもしれません知っているが、これらは基本的にアクティブなレコードですモデル化されたプログラムでは意味があります。 0m22.836

  • MEMBERのアクセステスト:簡単なベンチマーク、

    • LOCALアクセステストの後

      のさらに一部ながら

    0m32.648sローカルバージョンは〜33%高速でありますクラス。どうして?

  • 答えて

    19

    self.m += 1あなたはselfというローカル変数を検索して、あなただけのローカル変数を検索する必要がある場合はもちろんm

    という属性は、それは余分な工程を経ることなく高速になります見つけるしなければならないことを意味します。

    ボンネットの下に何が起こっているかを一読することが有用です。

    >>> import dis 
    >>> dis.dis(StressTestLocal.do_work) 
    18   0 LOAD_CONST    1 (0) 
           3 STORE_FAST    1 (m) 
    
    19   6 LOAD_FAST    1 (m) 
           9 LOAD_CONST    2 (1) 
          12 INPLACE_ADD   
          13 STORE_FAST    1 (m) 
    
    20   16 LOAD_FAST    1 (m) 
          19 LOAD_CONST    3 (2) 
          22 INPLACE_MULTIPLY  
          23 STORE_FAST    1 (m) 
          26 LOAD_CONST    0 (None) 
          29 RETURN_VALUE   
    >>> dis.dis(StressTestMember.do_work) 
    10   0 LOAD_FAST    0 (self) 
           3 DUP_TOP    
           4 LOAD_ATTR    0 (m) 
           7 LOAD_CONST    1 (1) 
          10 INPLACE_ADD   
          11 ROT_TWO    
          12 STORE_ATTR    0 (m) 
    
    11   15 LOAD_FAST    0 (self) 
          18 DUP_TOP    
          19 LOAD_ATTR    0 (m) 
          22 LOAD_CONST    2 (2) 
          25 INPLACE_MULTIPLY  
          26 ROT_TWO    
          27 STORE_ATTR    0 (m) 
          30 LOAD_CONST    0 (None) 
          33 RETURN_VALUE   
    
    +2

    +1非常に良い、明確な答え。 – Tadeck

    +0

    非常にいいです。これは受け入れに値する。 –

    +0

    ローカルスコープのクラス変数への新しい参照を作成することは賢明でしょうか?例えば、 'm = self.m'?このテストでは何の違いもありませんが、私の 'do_work()'は何百万回も走るループです。 –

    5

    ローカル名は、ローカル名がdictアクセスを必要としないような最適化を行うため、より高速です。一方、インスタンス属性はオブジェクトの__dict__にアクセスする必要があります。

    これは、ローカル名がグローバル名よりも高速な理由です。

    関連する問題