ホームページ >バックエンド開発 >Python チュートリアル >Python のデフォルト引数の可変性が最小驚きの原則に違反しているように見えるのはなぜですか?

Python のデフォルト引数の可変性が最小驚きの原則に違反しているように見えるのはなぜですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-12-31 18:14:09911ブラウズ

Why Does Python's Default Argument Mutability Seem to Violate the Principle of Least Astonishment?

デフォルト引数の可変性と最小驚きの原則

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]

この動作は、「劇的な設計上の欠陥」と見なす一部の人からの批判を集めています。ただし、その背後には論理的な説明があります。

Python の関数はファーストクラスのオブジェクトであり、他の型と同様に操作したり、変数に代入したりできることを意味します。 def ステートメントが実行されると、関数オブジェクトが作成されます。このオブジェクトには、関数のコードだけでなく、属性として保存されるデフォルトの引数も含まれています。

デフォルトでは、デフォルトの引数は関数呼び出し時ではなく関数定義時に評価されます。これは、プログラムの実行中にデフォルト引数の状態が変化する可能性があり、その結果、foo 関数で観察される動作が生じる可能性があることを意味します。

この設計上の決定は、一貫性を維持する必要性から生じています。デフォルトの引数が関数呼び出し時に評価される場合、def 行はハイブリッド ステートメントになり、バインディングの一部が定義と呼び出しの両方で発生します。このアプローチは、さらなる複雑さと潜在的な混乱を引き起こす可能性があります。

effbot が指摘したように、この動作には実際的な応用がないわけではありません。たとえば、次のコードを考えてみましょう。

def a():
    print("a executed")
    return []

def b(x=a()):
    x.append(5)
    print(x)

a executed
>>> b()
[5]
>>> b()
[5, 5]

ここでは、x のデフォルト値が関数定義時に評価され、b() が何回呼び出されたとしても、a() は 1 回だけ呼び出されます。

結論として、Python のデフォルト引数の変更可能性は、一貫性を優先し、ファーストクラス関数の原則に沿った意図的な設計上の選択です。最初は直観に反しているように思えるかもしれませんが、関数実装の制御性と柔軟性が向上します。

以上がPython のデフォルト引数の可変性が最小驚きの原則に違反しているように見えるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。