リスト内包はループ変数に書き込むが、ジェネレータは書き込まないのはなぜか?[重複しています]。
質問
リスト内包で何かすると、ローカル変数に書き込まれます。
i = 0
test = any([i == 2 for i in xrange(10)])
print i
これは "9" と表示されます。しかし、ジェネレータを使用すると、ローカル変数に書き込まれません。
i = 0
test = any(i == 2 for i in xrange(10))
print i
これは "0"と表示されます。
この違いには何か良い理由があるのでしょうか。これは設計上の決定なのでしょうか、それともジェネレータとリスト内包が実装されている方法による単なるランダムな副産物なのでしょうか。個人的には、リスト内包がローカル変数に書き込まない方が良いように思います。
どのように解決するのですか?
Pythonの生みの親であるGuido van Rossumは、このことについて書いたときに言及しています。 ジェネレータ式 は Python 3 に統一的に組み込まれました: (強調)
Python 3 では、リスト内包とジェネレーター式の等価性を向上させるために、もう 1 つの変更も行いました。Python 2 では、リスト内包はループ制御変数を周囲のスコープに "leaks" します。
x = 'before' a = [x for x in 1, 2, 3] print x # this prints '3', not 'before'
これはリスト内包のオリジナルの実装の産物です。これは何年もの間、Pythonの"汚い小さな秘密"の1つでした。これは、リスト内包を圧倒的に速くするための意図的な妥協として始まり、初心者によくある落とし穴ではありませんでしたが、間違いなく時々人を刺します。 ジェネレータ式では、私たちはこれを行うことができませんでした。ジェネレータ式はジェネレータを使用して実装され、その実行には別の実行フレームが必要です。したがって、ジェネレータ式は (特に短いシーケンスを反復する場合)、リスト内包よりも効率が悪かったのです。
しかし、Python 3 では、ジェネレーター式と同じ実装戦略を使用することで、リスト内包の "dirty little secret" を修正することにしました。したがって、Python 3 では、上記の例 (print(x) を使用するように変更後 :-) は 'before' を表示し、リスト内包の 'x' が周囲のスコープの 'x' を一時的にシャドウするがオーバーライドしないことを証明します。
というわけで、Python 3ではもうこのようなことは起こらないでしょう。
興味深いことに ディクショナリ これは、dict内包がPython 3からバックポートされ、すでにそのような修正がなされていたためです。
このトピックをカバーする他の質問もいくつかありますが、トピックを検索したときに、すでにそれらを見たことがあるのではないでしょうか?)
関連
-
[解決済み] Pythonの構文に新しいステートメントを追加することはできますか?
-
[解決済み] Djangoで2つの日付の間を選択する
-
[解決済み] 文字列のリストを内容に基づいてフィルタリングする
-
[解決済み] 範囲指定された浮動小数点数のランダムな配列を生成します。
-
[解決済み] pandasのタイムゾーンに対応したDateTimeIndexを、特定のタイムゾーンに対応したナイーブなタイムスタンプに変換する。
-
[解決済み] Cythonのコードを含むPythonパッケージはどのように構成すればよいのでしょうか?
-
[解決済み] tensorflowのCPUのみのインストールでダイナミックライブラリ 'cudart64_101.dll' を読み込めなかった
-
[解決済み] PyQtアプリケーションのスレッド化。QtスレッドとPythonスレッドのどちらを使うか?
-
[解決済み] Python Empty Generator 関数
-
[解決済み] Pythonでリストが空かどうかをチェックする方法は?重複
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] PythonでのAWS Lambdaのインポートモジュールエラー
-
[解決済み] SQLAlchemy: セッションの作成と再利用
-
[解決済み] PILからopenCVフォーマットへの変換
-
[解決済み] PythonでSVGからPNGに変換する
-
[解決済み] PyMongoで.sortを使用する
-
[解決済み] Ctrl-CでPythonスクリプトを終了できない
-
[解決済み] Python Logging でログメッセージが2回表示される件
-
[解決済み] Pythonの検索パスを他のソースに展開する
-
[解決済み] Django filter queryset __in for *every* item in list
-
[解決済み] リスト内包は、内包のスコープを越えても、名前を再束縛します。これは正しいのか?