2012-01-27 15 views
6

疑いがある場合は、通常、モジュールの上部にインポート文を配置します。しばしば、これは反復を減らします。これはうまくいきます。ただし、1つの関数(またはクラス)のみがインポートを必要とする場合は、パフォーマンスの低下がありますか?Python関数レベルでのインポート。モジュールレベル

この関数を呼び出すと、次のようなインポートが行われますか?

 def func(): 
     from task import test 

もしそうなら、それはわずかな効率であるかもしれないと思います。また、インポートされたオブジェクトはグローバル辞書に追加されないため、ガベージコレクションと変数スコープの高速化のためにいくつかの点を追加することができます。別のポスターでうまくいけば:

これは主に可変ルックアップによるものです。グローバルスコープで変数を検索するには、辞書検索が必要です。対照的に、コンパイラはローカル名を静的に決定し、それらをインデックスで参照するため、辞書検索は不要です。

これらの公平な仮定は完全に基底から外れていますか?

おかげ

+2

名前ルックアップのパフォーマンスについては、**問題ではありません。**まれに、コードを完成させたときに、コードが遅すぎてプロファイリングされていることがわかります。 – delnan

答えて

4

関数のインポートは、関数の実行時にのみインポートされます。 Pythonでは、すべてのステートメントが実行されたときに実行され、インポートは他のステートメントと同じステートメントであることに注意してください。最上位レベルのインポートはモジュールのインポート時にインポートされます。これはモジュール内のトップレベルのステートメントであるためです。

名前の検索に関する懸念は間違っています。違いはごくわずかで、プロファイリングに問題がある場合のみ考慮する必要があります。

モジュールを関数スコープにインポートするには、1)リファクタリングによって他の方法で解決できる可能性のある循環インポートの問題を修正する、または2)モジュールがオプションであり、関数がそうでない場合多くのユーザーが使用しています。 2)の場合、モジュールは完全に失われている可能性があり、誰かが関数を呼び出さなければ問題はありません。

+0

これはもっと理論的な質問でした。たとえ無視できなくても違いがあるようです。ありがとうNed – Ben

+0

それは最もpythonic方法ですか?私は、モジュールのルートで__init__.pyにインポートを行い、そこからすべてをインポートする人がいることが分かりました。特定の循環輸入を解決するために使用できますか? – radtek

3

は、バイトコードは、以下の2つの機能のためにどのように見えるかを見てみましょう:

def func1(): 
    """ test imported each time function is run """ 
    from task import test 
    test() 

def func2(): 
    """ test was imported at top of module """ 
    test() 

あなたは下記見ることができるように、func2()は、グローバルインポートtest機能を使って、ステップの節約します。 delnanさんのコメントで指摘したように、フロントまでこのことを考慮して

>>> dis.dis(func1) 
    3   0 LOAD_CONST    1 (-1) 
       3 LOAD_CONST    2 (('test',)) 
       6 IMPORT_NAME    0 (task) 
       9 IMPORT_FROM    1 (test) 
      12 STORE_FAST    0 (test) 
      15 POP_TOP 

    4   16 LOAD_FAST    0 (test) 
      19 CALL_FUNCTION   0 
      22 POP_TOP 
      23 LOAD_CONST    3 (None) 
      26 RETURN_VALUE 
>>> dis.dis(func2) 
    3   0 LOAD_GLOBAL    0 (test) 
       3 CALL_FUNCTION   0 
       6 POP_TOP 
       7 LOAD_CONST    1 (None) 
      10 RETURN_VALUE 

は、おそらく時期尚早な最適化です。

testがグローバル名前空間にあるため、検索パフォーマンスの問題が発生する可能性は低いです。あなたがこれを見ることができる最も顕著な方法は、testのハッシュコリジョンがあり、非常に頻繁に使用する別の名前があると、その第2の名前の検索に時間がかかることです。再び、まれなケースを前もって考慮する時期尚早の最適化。

+1

しかし、実際にはモジュールを2回以上インポートすることはなく、呼び出されるたびに必要かどうかを確認するだけです。 – delnan

+0

このようにレイアウトしていただきありがとうございます。それは便利です。 disライブラリに精通していなかった。 – Ben

0

非常に頻繁に呼び出されなければ、定義にインポートを入れるのは意味があると思います。

関連する問題