Python のドキュメントには、キーワード引数 (用語集) について次のように記載されています。
...変数名は、値が割り当てられる関数内のローカル名を指定します...
したがって、明示的に述べられていない限り、クラスの異なるインスタンスは本当に異なると思いました。ただし、次のコードは、クラスの両方のインスタンスの 1 つのメンバー変数を /same/ オブジェクトに参照します。明らかに、指定されたデフォルト値を介して (メソッドのキーワード辞書がクラス変数 (「静的」) であるかのように) 参照します。メンバーを変更するとすべて問題ありませんが、何らかの理由でそれが起こらない場合:
- コードがそのように動作する正当な理由があるのだろうかと思います。なぜなら、それは私がまったく期待するものではないからです (コードと出力のマーキングを参照してください)。
問題に対する適切な解決策があるかどうか (「コピー」を使用する以外に)。ありがとう。
class C: def setParams(self): self.e = [] def setParamsKw(self, kw=['default list']): # <----- kw arg. self.eKw = kw # <--- that member should # default to the # default argument # (use 'kw.copy()'?) def outputMember(): print " c1.e=", c1.e print " c2.e=", c2.e print " type(c1.e)=", type(c1.e) print " type(c2.e)=", type(c2.e) print " c1.e == c2.e:", c1.e == c2.e print " c1.e is c2.e:", c1.e is c2.e def outputMemberKw(): print " c1.eKw=", c1.eKw print " c2.eKw=", c2.eKw print " type(c1.eKw)=", type(c1.eKw) print " type(c2.eKw)=", type(c2.eKw) print " c1.eKw == c2.eKw:", c1.eKw == c2.eKw print " c1.eKw is c2.eKw:", c1.eKw is c2.eKw # <----- this result # is unexpected c1 = C() c2 = C() print " c1 == c2:", c1 == c2 print " c1 is c2:", c1 is c2 print "Calling setParams for both instances:" c1.setParams() c2.setParams() outputMember() print "Calling setParamsKw for both instances:" c1.setParamsKw() c2.setParamsKw() outputMemberKw() print "Now manually modifying members of c1:" c1.e = [1, 2, 3, 4, 5] c1.eKw = [1, 2, 3, 4, 5] print "e:" outputMember() print "eKw:" outputMemberKw()
出力:
c1 == c2: False
c1 is c2: False
Calling setParams for both instances:
c1.e= []
c2.e= []
type(c1.e)= <type 'list'>
type(c2.e)= <type 'list'>
c1.e == c2.e: True
c1.e is c2.e: False
Calling setParamsKw for both instances:
c1.eKw= ['default list']
c2.eKw= ['default list']
type(c1.eKw)= <type 'list'>
type(c2.eKw)= <type 'list'>
c1.eKw == c2.eKw: True
c1.eKw is c2.eKw: True
Now manually modifying members of c1:
e:
c1.e= [1, 2, 3, 4, 5]
c2.e= []
type(c1.e)= <type 'list'>
type(c2.e)= <type 'list'>
c1.e == c2.e: False
c1.e is c2.e: False
eKw:
c1.eKw= [1, 2, 3, 4, 5]
c2.eKw= ['default list']
type(c1.eKw)= <type 'list'>
type(c2.eKw)= <type 'list'>
c1.eKw == c2.eKw: False
c1.eKw is c2.eKw: False