week04_python関数のデフォルト値


デフォルトのスコープ
def foo(xyz=[]):
    xyz.append(10)
    print(xyz)

foo()#[10]
foo()#[10, 10]

なぜfoo関数を2回目に呼び出して印刷したのは[10,10]??
関数もオブジェクトであるため、pythonは関数のデフォルト値を属性に置き、この属性はこの関数オブジェクトのライフサイクル全体を伴う.
foo._の表示defaults__属性;
def foo(xyz=[], u='abc', z=123):
    xyz.append(1)
    return xyz

print(foo(), id(foo))#[1] 12588984
print(foo.__defaults__)#([1], 'abc', 123)
print(foo(), id(foo))#[1, 1] 12588984
print(foo.__defaults__)#([1, 1], 'abc', 123)

関数アドレスは変更されていません.つまり、関数というオブジェクトは変更されていません.呼び出すと、その属性_defaults__を使用して、すべての既定値を保存します.
xyzのデフォルト値は参照タイプであり、参照タイプの要素の変動はメタグループの変化ではありません.
        :

def foo(w, u='abc', z=123):
    u = 'xyz'
    z = 789
    print(w, u, z)

print(foo.__defaults__)#('abc', 123)
foo('magedu')#magedu xyz 789
print(foo.__defaults__)#('abc', 123)

属性__defaults__を選択して設定できます.
可変タイプのデフォルト値は、デフォルト値を使用すると、このデフォルト値を変更することができます.
时にはこの特性は良くて、时にはこのような特性はよくなくて、副作用があります;
どのようにして必要に応じて変更しますか?次の2つの方法があります.
def foo(xyz=[], u='abc', z=123):
    xyz = xyz[:]#    
    xyz.append(1)
    print(xyz)

print(foo.__defaults__)
foo()
print(foo.__defaults__)
foo()
print(foo.__defaults__)
foo([10])
print(foo.__defaults__)
foo([10, 5])
print(foo.__defaults__)

関数内のデフォルト値は変更されません.
xyzはいずれも入力パラメータまたはデフォルトパラメータのコピーであり、元のパラメータを変更したい場合は、何もできません.
def foo(xyz=None, u='abc', z=123):
    if xyz is None:
        xyz = []
    xyz.append(1)
    print(xyz)

foo()
print(foo.__defaults__)
foo()
print(foo.__defaults__)
foo([10])
print(foo.__defaults__)
foo([10, 5])
print(foo.__defaults__)

可変タイプのデフォルト値を使用するには、次の手順に従います.
デフォルト値Noneを使用するとリストが作成されます.
リストが入力されたら、このリストを変更します.
まとめ:
  • 最初の方法は、シャドウコピーを使用して新しいオブジェクトを作成し、受信パラメータ
  • を変更することはできません.
  • 第2の方法は、値の判断によって、入力オブジェクトの作成または変更を柔軟に選択することができる.この方式は柔軟で、応用が広範である.多くの関数の定義では,Noneという不変の値をデフォルトパラメータとして用いることが見られ,これは慣習と言える.