3

Python (2.6) は、この単純な一時変数 'a' を最適化できないようです。

行の長さを減らすために、いくつかのコードにローカル変数を割り当てるために使用します。

私にとってこれは、適切なコンパイラが自動的に実行できる単純な最適化です。

from dis import dis

def f(func):
  func()

def functioncall():
  print ' => function called'

def unoptimized():
  print 'in unoptimized'
  a = functioncall
  f(func=a)

def optimized():
  print 'in optimized'
  f(func=functioncall)

unoptimized()
optimized()

print 'dis(unoptimized)'
dis(unoptimized)
print 'dis(optimized)'
dis(optimized)

出力:

in unoptimized
 => function called
in optimized
 => function called
dis(unoptimized)
 10           0 LOAD_CONST               1 ('in unoptimized')
              3 PRINT_ITEM
              4 PRINT_NEWLINE

 11           5 LOAD_GLOBAL              0 (functioncall)
              8 STORE_FAST               0 (a)

 12          11 LOAD_GLOBAL              1 (f)
             14 LOAD_CONST               2 ('func')
             17 LOAD_FAST                0 (a)
             20 CALL_FUNCTION          256
             23 POP_TOP
             24 LOAD_CONST               0 (None)
             27 RETURN_VALUE
dis(optimized)
 15           0 LOAD_CONST               1 ('in optimized')
              3 PRINT_ITEM
              4 PRINT_NEWLINE

 16           5 LOAD_GLOBAL              0 (f)
              8 LOAD_CONST               2 ('func')
             11 LOAD_GLOBAL              1 (functioncall)
             14 CALL_FUNCTION          256
             17 POP_TOP
             18 LOAD_CONST               0 (None)
             21 RETURN_VALUE

これを自動的に削除できないのはなぜですか?

 11           5 LOAD_GLOBAL              0 (functioncall)
              8 STORE_FAST               0 (a)
4

4 に答える 4

5

Python の標準実装である CPython は、あまり最適化を行いません。これは、ソース コードからバイトコードへの非常に簡単な変換です。いくつかの最適化が組み込まれています (if __debug__それらの 1 つであるコードの削除または巻き上げ)。ある種のピープホール オプティマイザがあると思いますが、コンパイル フェーズは合理的に高速であることを意図していると思います。分析。

保守性もコア Python 開発者にとって重要な要素のようです。これは2009 年のスレッドで、デッド コードを削除するためのパッチが検討された後、コンパイラの保守性が低下するため拒否されました。

高性能が必要な場合は、CPython 以外が必要です。おそらくPyPyが役立つでしょう。Python は一般に、ランタイムではなくプログラマーの時間を節約するように最適化されています。バイトコードにデッド コードを含めたくない場合は、ソース コードに含めないでください。:-)

于 2013-09-24T15:20:10.060 に答える
1

原則として、Python インタープリターはこれを最適化できます。

実際には、人々が Python でプログラミングするのは、Python で書かれたコードが速いからではなく、コードを書くのが速いからです。したがって、この特定のケースでは、プログラマーは最適化を期待されています。

于 2013-09-24T15:20:49.250 に答える
0

Python では、ソース コードが完全に消えるわけではありませんdef。ステートメントは、関数オブジェクトを作成する実行可能なステートメントです。あなたは、最適化という名目で要求された以外のことをpythonが巧妙に行わない理由を尋ねています。

この種の最適化は、必要に応じて lint ツールの助けを借りて、手作業で簡単に実行できます。発生する可能性のある予期しない結果を導入する価値はありません。やはりpythonのポイントは読み書きのしやすさです。

于 2013-09-24T15:20:56.730 に答える
0

TL;DR: それは機能です。

このタイプの最適化はデフォルトでは実行されるべきではないと思います。なぜならはと同等ではないからです: Python には設計上ここにある副作用があります。y=g(f(x))a=f(x) ; y=g(a)

ローカル名前空間は、Python 自体からアクセスできるように設計されています。明確に定義された API があります。eval関数とステートメントのドキュメントexec(Python >= 2.4) には、「提供されている場合、ローカルは任意のマッピング オブジェクトにすることができる」と記載されています。

考えられるアプリケーションの 1 つは、Python デバッガーを Python で作成することです。dictローカル名前空間での読み取り/書き込みのたびに GUI イベントがトリガーされるようにサブクラス化できます。aとの間の中間結果を観察できるようにa=f(x)なりy=g(a)ました。その可能性がなければ、CPython 仮想スタック、または他の Python 実装で使用されているものを検査する必要があります。

デバッグ以外にも、この機能の他の用途が考えられます。Python をビデオ ゲーム エンジンに埋め込むことは想像に難くありません。ストーリー、クエスト、キャラクター、イベントなどを担当するデザイナーは、コードを書くためではなく、想像力をゲーム コンテンツに変換するためにここにいます。彼らの生活を楽にするために、いくつかの事前ロードされた値やリアルタイムの値が付属する特別なローカル名前空間でスクリプトを実行できます。名前my_hptheir_hpは常に、スクリプトをトリガーした「攻撃」イベントに関与する 2 つのクリーチャーの現在のヒットポイント数を返す/設定します。私の設計者はself.、常に入力する必要はありません (さらに、クラスやオブジェクトについても知りません)。ある意味では、my_hpクリーチャーに対してローカルであり、明示的なクラス/インスタンスの逆参照を必要としないことを除いて、グローバルまたは記述子のように機能します。これは、スクリプトを解析して、いつ何かselfの前に追加する必要があるかを推測しようとするよりも、そのように実装する方がはるかに簡単です。

要するに、仮想マシンがコードで何をするかは決してわからないため、同じように見えることが常にそうであるとは限りません。

于 2015-08-18T14:31:51.987 に答える