可能性のある複製:
インスタンスメソッドの結果としてのパラメーターのデフォルト値
Pythonの関数パラメーターにデフォルト値を設定することは可能ですが、
def my_function(param_one='default')
...
現在のインスタンス(自己)にアクセスできないようです:
class MyClass(..):
def my_function(self, param_one=self.one_of_the_vars):
...
私の質問:
次のように書かれています。
def my_function(self, param_one=None): # Or custom sentinel if None is vaild
if param_one is None:
param_one = self.one_of_the_vars
そして、self
は関数が開始するまで実際には存在しないという性質のため、Pythonでは決して起こらないと言っても安全だと思います...(参照することはできません。独自の定義-他のすべてと同様)
例:d = {'x': 3, 'y': d['x'] * 5}
はできません
あなたが思っている以上に多くのことがあります。デフォルトはstatic(=oneオブジェクトを指す定数参照) )および定義のどこかに保存されています。メソッド定義時に評価されます。インスタンスではなく、classの一部として。定数であるため、self
に依存できません。
以下に例を示します。それは直感に反しますが、実際には完全に理にかなっています:
def add(item, s=[]):
s.append(item)
print len(s)
add(1) # 1
add(1) # 2
add(1, []) # 1
add(1, []) # 1
add(1) # 3
これは1 2 1 1 3
を出力します。
と同じように機能するため
default_s=[]
def add(item, s=default_s):
s.append(item)
明らかに、default_s
を変更すると、これらの変更が保持されます。
以下を含むさまざまな回避策があります。
def add(item, s=None):
if not s: s = []
s.append(item)
または、これを行うことができます:
def add(self, item, s=None):
if not s: s = self.makeDefaultS()
s.append(item)
その後、メソッドmakeDefaultS
はself
にアクセスできます。
別のバリエーション:
import types
def add(item, s=lambda self:[]):
if isinstance(s, types.FunctionType): s = s("example")
s.append(item)
ここで、s
のデフォルト値は工場出荷時の機能です。
これらすべての手法を組み合わせることができます。
class Foo:
import types
def add(self, item, s=Foo.defaultFactory):
if isinstance(s, types.FunctionType): s = s(self)
s.append(item)
def defaultFactory(self):
""" Can be overridden in a subclass, too!"""
return []
パラメータのデフォルト値は、「コンパイル」時に1回評価されます。したがって、明らかにself
にアクセスすることはできません。古典的な例は、list
がデフォルトパラメータです。要素を追加すると、パラメーターのデフォルト値が変更されます!
回避策は、別のデフォルトパラメータ(通常はNone
)を使用してから、変数をチェックして更新することです。
ここで複数の誤った仮定があります。まず、関数はインスタンスではなくクラスに属します。つまり、実際の関数はクラスの2つのインスタンスで同じです。次に、デフォルトのパラメーターはコンパイル時に評価され、定数です(定数オブジェクト参照のように、パラメーターが可変オブジェクトの場合は変更できます)。したがって、デフォルトパラメータでself
にアクセスすることはできず、アクセスできなくなります。