Pythonはどのようにデフォルトのパラメータの関数を定義しますか?


問題
関数または方法を定義したいです。1つ以上のパラメータはオプションであり、デフォルト値があります。
ソリューション
オプションのパラメータがある関数を定義するのはとても簡単です。直接関数定義でパラメータにデフォルト値を指定して、パラメータリストの最後に置いてもいいです。たとえば:

def spam(a, b=42):
  print(a, b)

spam(1) # Ok. a=1, b=42
spam(1, 2) # Ok. a=1, b=2
デフォルトのパラメータが変更可能なコンテナであれば、リスト、セット、または辞書のように、Noneをデフォルトとして使用することができます。

# Using a list as a default value
def spam(a, b=None):
  if b is None:
    b = []
  ...
デフォルトの値を提供したいのではなく、デフォルトのパラメータだけをテストしたいなら、次のように書いてもいいです。

_no_value = object()

def spam(a, b=_no_value):
  if b is _no_value:
    print('No b value supplied')
  ...
この関数をテストします。

>>> spam(1)
No b value supplied
>>> spam(1, 2) # b = 2
>>> spam(1, None) # b = None
>>>
注意深く観察すると,一つのNone値を伝達する場合と,値を伝えない場合とでは異なることが分かった。
討論する
標準値パラメータを持つ関数を定義するのは簡単ですが、これだけではなく、ここでも議論を深めていくものがあります。
まず、デフォルトのパラメータの値は、関数が定義されている時に一度だけ与えられます。次の例を実行してみます。

>>> x = 42
>>> def spam(a, b=x):
...   print(a, b)
...
>>> spam(1)
1 42
>>> x = 23 # Has no effect
>>> spam(1)
1 42
>>>
私たちがxの値を変えると、デフォルトのパラメータ値には影響がないことに注意してください。これは関数が定義されているときに、そのデフォルト値が確定されているからです。
次に、デフォルトのパラメータの値は、None、True、False、数字または文字列のような可変的ではないオブジェクトであるべきである。特に、下記のようにコードを書かないでください。

def spam(a, b=[]): # NO!
  ...
このようにすれば、デフォルト値が他のところで修正されると、さまざまなトラブルが発生します。これらの変更は、次の関数の呼び出し時の標準値に影響します。たとえば:

>>> def spam(a, b=[]):
...   print(b)
...   return b
...
>>> x = spam(1)
>>> x
[]
>>> x.append(99)
>>> x.append('Yow!')
>>> x
[99, 'Yow!']
>>> spam(1) # Modified list gets returned!
[99, 'Yow!']
>>>
この結果はあなたが望むものではないはずです。このような状況を避けるためには、デフォルト値をNoneとして設定し、関数内でそれをチェックするのがベストです。前の例はこのようにしています。
None値をテストする際にはis操作子を使うことが重要であり、このような方案のキーポイントでもある。時々、みんなは次のようなミスをします。

def spam(a, b=None):
  if not b: # NO! Use 'b is None' instead
    b = []
  ...
このように書かれている問題は、None値は確かにFalseとして扱われていますが、他のオブジェクト(長さ0の文字列、リスト、タプル、辞書など)がFalseとして扱われています。そのため、上のコードは他の入力も入力していないと間違えてしまいます。たとえば:

>>> spam(1) # OK
>>> x = []
>>> spam(1, x) # Silent error. x value overwritten by default
>>> spam(1, 0) # Silent error. 0 ignored
>>> spam(1, '') # Silent error. '' ignored
>>>
最後の問題は微妙です。つまり、あるオプションパラメータが使用者によって伝達されるかどうかをテストする必要があります。このとき注意しなければならないのは、None、0またはFalse値のようなデフォルト値でユーザが提供する値をテストしてはいけないことです。ですから、他の解決策が必要です。
この問題を解決するために、上のようなユニークなプライベートオブジェクトのインスタンスを作成することができます。ノの_value変数みたいです。関数では、このインスタンスと同じかどうかを確認することによって、伝達パラメータの値を判断することができます。ここの考えはユーザーがこれを伝えることが不可能です。ノの_入力としてvalueの例を示します。したがって、ここではこの値をチェックすることにより、あるパラメータが渡されたかどうかを確認することができます。
ここではobject()の使用はあまり見られません。objectはpythonのすべての種類の基本クラスです。objectクラスのインスタンスを作成することができますが、これらのインスタンスは実用的なものではありません。有用な方法もないし、インスタンスデータもありません。唯一できるのは同じ性をテストすることです。これはちょうど私の要求に合っています。関数の中では同じテストが必要なだけです。
以上はPythonがどのようにデフォルトパラメータの関数の詳細を定義していますか?Pythonがデフォルトパラメータの関数を定義していることに関する資料は他の関連記事に注目してください。