[解決済み] 最小限の驚き」と「変更可能なデフォルトの引数
質問
Pythonを長くいじっていると、次のような問題に悩まされることがあります。
def foo(a=[]):
a.append(5)
return a
Pythonの初心者は、この関数が常に1つの要素からなるリストを返すと思うでしょう。
[5]
. しかし、その結果は全く異なり、(初心者にとっては)非常に驚くべきものです。
>>> foo()
[5]
>>> foo()
[5, 5]
>>> foo()
[5, 5, 5]
>>> foo()
[5, 5, 5, 5]
>>> foo()
以前、私の上司がこの機能に初めて遭遇し、「この言語の劇的な設計上の欠陥だ」と言ったことがあります。私は、この動作には根本的な説明があり、内部を理解していなければ、確かに非常に不可解で、予想外の動作です、と答えました。しかし、次の質問には(自分では)答えられませんでした。「デフォルトの引数を関数実行時ではなく、関数定義時にバインドする理由は何ですか?C言語でスタティック変数をバグを出さずに使っていた人は本当にいたのでしょうか?
編集 :
Baczekが興味深い例を挙げている。 . 皆さんのほとんどのコメントと一緒に 特にユタールさんの と、さらに詳しく説明しました。
>>> def a():
... print("a executed")
... return []
...
>>>
>>> def b(x=a()):
... x.append(5)
... print(x)
...
a executed
>>> b()
[5]
>>> b()
[5, 5]
私には、パラメータのスコープを関数内に置くか、関数と一緒に置くか、という設計上の判断があったように思えますが?
関数の内部でバインディングを行うと、次のようなことになります。
x
は、関数が呼ばれたときに、定義されているのではなく、指定されたデフォルトに事実上束縛されています。
def
の行は、(関数オブジェクトの)結合の一部が定義時に起こり、(デフォルトパラメータの割り当てが)関数の呼び出し時に起こるという意味で、quot;hybrid" になります。
実際の動作は、より一貫しています。その行のすべてが、その行が実行されたとき、つまり関数定義時に評価されます。
解決方法は?
実は、これは設計上の欠陥でもなければ、内部やパフォーマンスのせいでもないのです。
これは、Pythonの関数がファーストクラスのオブジェクトであり、単なるコードの一部ではないという事実から来ています。
関数は、その定義に基づいて評価されるオブジェクトです。デフォルトのパラメータは一種のメンバーデータであり、したがって、他のオブジェクトとまったく同様に、呼び出しごとにその状態が変化する可能性があります。
いずれにせよ、この動作の理由については、Effbotが非常に素晴らしい説明をしてくれています。
Pythonにおけるパラメータのデフォルト値
.
とても分かりやすいので、関数オブジェクトの仕組みを知るために読むことをお勧めします。
関連
-
ピローによる動的キャプチャ認識のためのPythonサンプルコード
-
[解決済み】numpyの配列連結。"ValueError:すべての入力配列は同じ次元数でなければならない"
-
[解決済み] Pythonのリストメソッドであるappendとextendの違いは何ですか?
-
[解決済み] オブジェクト名の前のシングルアンダーコアとダブルアンダーコアの意味は何ですか?
-
[解決済み] シェルコマンドの実行と出力のキャプチャ
-
[解決済み] リストとタプルの違いは何ですか?
-
[解決済み】__str__と__repr__の違いは何ですか?
-
[解決済み】type()とisinstance()の違いは何ですか?)
-
[解決済み】Djangoでnull=Trueとblank=Trueの違いは何ですか?
-
[解決済み】プログラムを停止/終了させることなく、完全な例外トレースバックをキャッチして表示する方法は?
最新
-
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 jiabaライブラリの使用方法について説明
-
Evidentlyを用いたPythonデータマイニングによる機械学習モデルダッシュボードの作成
-
[解決済み] [Solved] sklearn error ValueError: 入力に NaN、infinity または dtype('float64') に対して大きすぎる値が含まれている。
-
[解決済み】ilocが「IndexError: single positional indexer is out-of-bounds」を出す。
-
[解決済み】 NameError: グローバル名 'xrange' は Python 3 で定義されていません。
-
[解決済み】NameError: 名前 'self' が定義されていません。
-
[解決済み】「OverflowError: Python int too large to convert to C long" on windows but not mac
-
[解決済み】django インポートエラー - core.managementという名前のモジュールがない
-
[解決済み] Pythonで空の辞書が危険なデフォルト値であるのはなぜですか?[重複しています]。
-
[解決済み] Pythonのコンストラクタとデフォルト値 [重複] [重複