2

私はインライン化について知っていますが、私がチェックしたところ、インライン化は Python のコンパイラによって行われていません。

私の質問は次のとおりです:変換するpythonのコンパイラで最適化はありますか:

print myList.__len__()
for i in range(0, myList.__len__()):
    print i + myList.__len__()

l = myList.__len__()
print l
for i in range(0, l):
    print i + l

それで、それはコンパイラによって行われますか?
そうでない場合: 自分でやる価値はありますか?

おまけの質問(あまり関係ありません):私はたくさんの関数を持っているのが好きです(読みやすくするためにIMHOの方が良いです)...Pythonにインライン化がないのと同じように、これは避けるべきものですか(たくさんの関数)?

4

2 に答える 2

6

いいえ、ありません。disモジュールを使用してコードをバイトコードにコンパイルすることで、Python の動作を確認できます。

>>> def test():
...     print myList.__len__()
...     for i in range(0, myList.__len__()):
...         print i + myList.__len__()
... 
>>> import dis
>>> dis.dis(test)
  2           0 LOAD_GLOBAL              0 (myList)
              3 LOAD_ATTR                1 (__len__)
              6 CALL_FUNCTION            0
              9 PRINT_ITEM          
             10 PRINT_NEWLINE       

  3          11 SETUP_LOOP              44 (to 58)
             14 LOAD_GLOBAL              2 (range)
             17 LOAD_CONST               1 (0)
             20 LOAD_GLOBAL              0 (myList)
             23 LOAD_ATTR                1 (__len__)
             26 CALL_FUNCTION            0
             29 CALL_FUNCTION            2
             32 GET_ITER            
        >>   33 FOR_ITER                21 (to 57)
             36 STORE_FAST               0 (i)

  4          39 LOAD_FAST                0 (i)
             42 LOAD_GLOBAL              0 (myList)
             45 LOAD_ATTR                1 (__len__)
             48 CALL_FUNCTION            0
             51 BINARY_ADD          
             52 PRINT_ITEM          
             53 PRINT_NEWLINE       
             54 JUMP_ABSOLUTE           33
        >>   57 POP_BLOCK           
        >>   58 LOAD_CONST               0 (None)
             61 RETURN_VALUE        

ご覧のとおり、__len__属性は毎回検索され、呼び出されます。

Python は、特定のメソッドが呼び出し間で何を返すかを知ることができません__len__。メソッドも例外ではありません。Python が呼び出し間で返される値が同じであると想定して最適化しようとすると、数え切れないほどのさまざまな問題に遭遇することになり、マルチスレッドの使用はまだ試していません。

フックを直接len(myList)呼び出さずに、を使用する方がはるかに良いことに注意してください。__len__()

print len(myList)
for i in xrange(len(myList):
    print i + len(myList)
于 2012-11-14T14:57:25.763 に答える
1

いいえ、あなたが求めている最適化は CPython コンパイラによって行われません。実際、CPython コンパイラによって最適化が行われることはほとんどありません。

自分で確認し、import dis質問しているようなコードで関数を逆アセンブルするには: dis.dis(func).

これが最適化されていない理由は、属性 ( のようなメソッドでさえ__len__) が次にアクセスされたときに完全に異なるオブジェクトになる可能性が十分にあるからです。もちろん、これはめったに起こりませんが、Python はそれをサポートしています。

属性へのアクセスには時間がかかるため、繰り返し使用する属性への参照を (特にローカル変数に) 格納すると、コードの実行速度が向上します。ただし、可読性が低下するため、特定のコードがボトルネックであることがわかるまで適用しないでください。あなたの場合、印刷に費やされる時間は、属性へのアクセスを簡単に圧倒します。

最終的な分析では、パフォーマンスが最重要事項である場合、そもそも Python 以外のものを使用していたのではないでしょうか?

于 2012-11-14T14:59:24.093 に答える