問題タブ [python-internals]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
python - Python Bytecode Run in CPython とはどのくらい正確ですか?
Python がどのように機能するかを理解しようとしています (常に使用しているためです!)。私の理解では、python script.py のようなものを実行すると、スクリプトがバイトコードに変換され、インタプリタ/VM/CPython (実際には単なる C プログラム) が python バイトコードを読み取り、それに応じてプログラムを実行します。
このバイトコードはどのように読み込まれますか? C でテキスト ファイルを読み取る方法に似ていますか。Python コードがどのように機械語コードに変換されるのかわかりません。Python インタープリター (CLI の python コマンド) は、実際には既にマシン コードに変換されたプリコンパイル済みの C プログラムであり、Python バイトコード ファイルはそのプログラムを通過するだけなのでしょうか? 言い換えれば、私の Python プログラムは実際には機械語に変換されないのでしょうか? Python インタープリターは既にマシン コードに組み込まれているので、スクリプトを記述する必要はありませんか?
python - リスト内包表記フィルタリング - 「set() トラップ」
合理的に一般的な操作はlist
、別のものに基づいて1 つをフィルタリングすることlist
です。人々はすぐに次のことに気付きます。
大きな入力に対しては遅いです - それは O(n*m) です。うん。どうすればこれをスピードアップできますか? a を使用しset
て、フィルタリング ルックアップ O(1) を作成します。
これにより、全体的に O(n) の動作が適切になります。しかし、ベテランのコーダーでさえ、 The Trap ™に陥るのをよく見かけます。
あっ!Python は 1回だけでなくset(list_2)
毎回ビルドするため、これも O(n*m)です。
私はそれが話の終わりだと思った-pythonはそれを最適化してset
一度だけ構築することはできない。落とし穴に注意してください。それと一緒に暮らす必要があります。うーん。
ええ、python (3.3)は集合リテラルを最適化できます。f()
おそらく aLOAD_GLOBAL
を aに置き換えるため、この場合よりもさらに高速ですLOAD_FAST
。
Python 2 は特にこの最適化を行いません。私はpython3が何をしているのかをさらに調査しようとしましたが、残念ながらdis.dis
理解表現の内部を調べることはできません. 基本的に興味深いものはすべて に変わりますMAKE_FUNCTION
。
だから今私は疑問に思っています-なぜpython 3.xはセットリテラルを最適化して1回だけビルドすることができset(list_2)
ますか?
python - CPython Dicts が負の 1 と負の 2 のハッシュ値の影響を受けないのはなぜですか?
ハッシュ テーブルは高パフォーマンスのマッピングであると想定されており、Python dict はハッシュ テーブルで実装されているため、高パフォーマンスでもあります。しかし、負の整数のハッシュ値を見ると、奇妙な結果に遭遇しました。
しかし、これは明らかに辞書には影響しません:
なぜこれが起こるのですか? また、辞書を使用しても影響を受けないのはなぜですか?
python - Python での変数への参照の解決方法
このメッセージは多くの例で少し長くなりますが、Python 2.7 での変数と属性ルックアップの完全なストーリーをよりよく理解するのに役立つことを願っています。
コードブロック(モジュール、クラス定義、関数定義など)と変数バインディング(代入、引数の宣言、クラスと関数の宣言、for ループなど)
ドットなしで呼び出すことができる名前には変数という用語を使用し、オブジェクト名で修飾する必要がある名前には属性という用語を使用しています (オブジェクト obj の属性 x の obj.x など)。
Python には、すべてのコード ブロックに対して 3 つのスコープがありますが、関数は次のとおりです。
- ローカル
- グローバル
- ビルトイン
関数専用の Python には 4 つのブロックがあります (PEP 227 によると)。
- ローカル
- 囲み関数
- グローバル
- ビルトイン
変数をバインドしてブロック内で見つけるためのルールは非常に単純です。
- ブロック内のオブジェクトに変数をバインドすると、変数がグローバルに宣言されていない限り (その場合、変数はグローバル スコープに属します)、この変数はこのブロックに対してローカルになります。
- 変数への参照は、すべてのブロックに対してルール LGB (ローカル、グローバル、ビルトイン) を使用して検索されますが、関数は
- 変数への参照は、関数に対してのみルール LEGB (ローカル、エンクロージング、グローバル、ビルトイン) を使用して検索されます。
このルールを検証し、多くの特殊なケースを示す例を教えてください。それぞれの例について、私の理解を示します。間違っている場合は修正してください。最後の例については、結果がわかりません。
例 1:
クラスのネストされたスコープはなく (ルール LGB)、クラス内の関数は、修飾名 (この例では self.x) を使用しないとクラスの属性にアクセスできません。これは PEP227 で詳しく説明されています。
例 2:
ここで、関数内の変数は LEGB ルールを使用して検索されますが、クラスがパスにある場合、クラスの引数はスキップされます。繰り返しますが、これは PEP 227 が説明していることです。
例 3:
Python などの動的言語では、すべてが動的に解決されることが期待されます。しかし、これは関数には当てはまりません。ローカル変数はコンパイル時に決定されます。PEP 227 および http://docs.python.org/2.7/reference/executionmodel.htmlは、この動作をこのように説明しています
「名前バインディング操作がコード ブロック内のどこかで発生した場合、ブロック内の名前のすべての使用は、現在のブロックへの参照として扱われます。」
例 4:
しかし、PEP227 のこのステートメントは、「コード ブロック内の任意の場所で名前バインディング操作が発生した場合、ブロック内の名前のすべての使用は、現在のブロックへの参照として扱われます。」コードブロックがクラスの場合は間違っています。また、クラスについては、コンパイル時ではなく、実行時にクラスの名前空間を使用してローカルの名前バインディングを行うようです。その点で、PEP227 と Python doc の実行モデルは誤解を招きやすく、一部が間違っています。
例 5:
このコードの私の理解は次のとおりです。命令 x = x は、最初に式の右手 x が参照しているオブジェクトを調べます。その場合、オブジェクトはクラス内でローカルに検索され、次にルール LGB に従って、文字列 'x in module' であるグローバル スコープで検索されます。次に、MyClass へのローカル属性 x がクラス ディクショナリに作成され、文字列オブジェクトを指します。
例 6:
ここで、説明できない例を示します。これは例 5 に非常によく似ています。ローカルの MyClass 属性を x から y に変更しているだけです。
その場合、MyClass の x 参照が最も内側の関数で検索されるのはなぜですか?
python - Python の 'len' 関数が __len__ メソッドよりも速いのはなぜですか?
Python では、オブジェクトのメソッドlen
を呼び出してコレクションの長さを取得する関数です。__len__
__len__()
したがって、 の直接呼び出しは、少なくとも と同じくらい高速であると予想されlen()
ます。
しかし、上記のコードでテストした結果は、より高速であることが示さlen()
れています。なんで?
python - `a` のスライス (例: `a[1:] == a[:-1]`) は `a` のコピーを作成しますか?
私の友人が次の Python コードを見せてくれました。
a
すべての項目が同一である場合に True を返します。
私は、このコードは一目で理解するのが難しく、さらにa
、比較のために のコピーが 2 つ作成されるため、メモリの使用効率が悪いと主張しました。
Python を使用dis
して、ボンネットの背後で何が起こっているかを確認しましたa[1:]==a[:-1]
。
それは 2 つのスライス コマンドに要約されます -SLICE+1
とSLICE+2
. ドキュメントは、これらのオペコードが実際に の新しいコピーを作成するのかa
、それとも単なる参照を作成するのかについて明確ではありません。
- SLICE コマンドはコピーします
a
か? - 答えは Python の実装 (Cython、Jython) によって異なりますか?
アップデート
このスニペットは明らかに判読不能で紛らわしいので、実際のコードで使用するつもりはありません。私の関心は純粋に技術的なものです - スライスがリストをコピーするかどうか、そして答えが状況によって異なるかどうかです。
python - Python スワッピング リスト
Python では、リストを別のリストに割り当てると、次のようになります。
これで b と a は同じリストを指します。ここで、2 つのリストを考えます。
では、それらが他のデータ型と同じように交換され、両方が同じリストを指していないのはなぜでしょうか?
python - ジェネレーターを書くか、ジェネレーターを返しますか?
コンテナー クラス内で、そのアイテム (またはそのアイテムの変換、またはそのアイテムのサブセット) を反復処理する場合は、ジェネレーター ( など)を作成するか、ジェネレーター ( など)f
を返すg
ことができます。
を介してジェネレーターに情報を渡す必要はありませんsend
。
どうやら、どちらの方法も(表面では)同じように動作します。
どのアプローチが望ましいですか?またその理由は?
オーバーヘッドが少ないアプローチ、または私が見つけられない他の利点があるアプローチはどれですか?
python - 同じ Python モジュールの 2 つのインスタンス?
「a!」を出力するだけの単一の関数を持つ Python モジュールを作成しました。Python インタープリターを開き、モジュールを 2 つの異なる構文でインポートしました
この時点で、 func を変更して別のものを出力し、再度評価します
モジュールがリロードされていないため、これは当然のことです。次に、モジュールをリロードし、両方の機能が更新されることを期待しましたが、次のようになりました。
a.func だけが更新されるようです。Python は同じモジュールのインスタンスを 1 つだけ保持しているといつも思っていましたが、現在は 2 つあるようです。私の主張を検証するためにさらにテストを行い、モジュールの最上位に print ステートメントを追加し、インタープリターを再起動して再度インポートしました。
「モジュールがインポートされました」が2回表示されると思っていたので、これはさらに混乱します。私が行った 3 番目の実験は、グローバル変数の実験でした。
モジュールのインスタンスは 1 つですが、内部のオブジェクトのインスタンスは異なるのでしょうか? このような動作でGevent のモンキー パッチを実装するにはどうすればよいでしょうか?