2017-01-05 10 views
7

Thesetwo質問の中では、機能の内側とモジュールの上部の間にimportを使用してください。私は、私の輸入品を一番上に置くことに納得する必要はありません。それを行う良い理由があります。しかし、技術的な問題をよりよく理解するために、私はフォローアップをお願いしたい。クロージャを使用して関数のインポートを最適化できますか?

クロージャを使用し、関数の最初の実行時にのみインポートすることで、パフォーマンスを最大限に引き出すことができますか?

具体

、次のようなコードがあるとします。

def get_version(): 
    import sys 
    return sys.version 

:あなたは機能がこれまでに呼び出された場合にのみ発生するので、あなたが内部を移動するインポートをしたい

import sys 
def get_version(): 
    return sys.version 

をしかし、今度はの場合はが多く呼び出されますので、もっと複雑なものを試してみてください:

def _get_version(): 
    import sys 

    def nested(): 
     return sys.version 

    global get_version 
    get_version = nested 
    return nested() 
get_version = _get_version 

少なくとも基本的なパフォーマンステストでは、この最後のオプションが最初のものよりわずかに遅い(〜110%)が、2番目のものよりもはるかに高速であることが示されています。


まず、これは実際には機能しますか?私の測定値は、2番目の例がもっとうまくいくか、それとも私が物を測定したかの人工物であることを正確に表していますか?

第2に、関数が初めて実行されたときを超えてクロージャからの減速がありますか?逆参照

+0

ピア機能の場合、 'functools'の' lru_cache'デコレータを使用することができます。それが素晴らしいアイデアであるかどうかはわかりませんが、最初に実行した後に関数の結果をキャッシュします。 – sytech

+1

@sytech: 'lru_cache'キャッシュテストはかなり重く、インポートのような軽量なもの(初期のファイルロードを過ぎても名前をバインドするものではありません)のパフォーマンスを大幅に向上させることはできません。 –

答えて

3

クロージャーがどの速くグローバル検索よりではありません。また

>>> import sys 
>>> sys.version_info 
sys.version_info(major=3, minor=6, micro=0, releaselevel='final', serial=0) 
>>> from timeit import timeit 
>>> glob = 'foo' 
>>> def f1(): return glob 
... 
>>> def closure(): 
...  closed_over = 'bar' 
...  def f2(): 
...   return closed_over 
...  return f2 
... 
>>> f2 = closure() 
>>> timeit(f1, number=10**7) 
0.8623221110319719 
>>> timeit(f2, number=10**7) 
0.872071701916866 

、それはが速くあったとしても、読みやすさに対するトレードオフは速くオプションをするときのために利用可能な、確かでない場合は、それだけの価値はありませんコードを最適化する必要があります。あなたが本当に適切なハイブリッドは、関数の引数のデフォルト値を使用している、タイトなループから呼び出されるコードを最適化する必要がある場合

地元の人々は、常に、最速のオプションです:

import sys.version 

def get_version(_sys_version=sys.version): 
    return _sys_version 

あなたがの影響を懸念している場合起動時のインポートからの初期ファイル読み込みではなく、代わりにpy-demandimport projectを参照する必要があります。これは、初めてモジュールを読み込むまで延期します。

+1

はい、私の質問に書かれているように、測定値が少し遅いことが示されました。ポイントは、あなたの関数の引数の例では欠けている唯一のimport-if-calledプロパティを保持しながら速度を最適化することでした。 – otus

+0

これはただの仮説ですが、py-demandimportプロジェクトは私が実際に使うことのできるもののようです。ありがとう。 – otus

関連する問題