24

みんな、私は最近pythonを始めたばかりで、オプションのパラメーターと混同しています。たとえば、次のようなプログラムがあるとします。

class B:
   pass

class A:
    def __init__(self, builds = B()):
        self.builds = builds

A を 2 回作成すると

b = A()
c = A()

ビルドを印刷します

print b.builds
print c.builds

まったく同じオブジェクトを使用していることがわかりました。

<__main__.B instance at 0x68ee0>
<__main__.B instance at 0x68ee0>

しかしb、ビルドの内部状態を変更すると、cオブジェクト内の状態も変更されるため、それは私が望むものではありません。

このオプション パラメータの構文を使用して、このオプション パラメータを毎回再作成することは可能ですか?

4

3 に答える 3

47

デフォルト値を効果的に使用するには、デフォルト値がどのように機能するかを理解する必要があります。

関数はオブジェクトです。そのため、属性があります。したがって、この関数を作成すると:

>>> def f(x, y=[]):
        y.append(x)
        return y

オブジェクトを作成しました。その属性は次のとおりです。

>>> dir(f)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__',   
'__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__',    
'__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 
'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 
'func_name']

それらの1つはですfunc_defaults。それは有望に聞こえますが、そこには何がありますか?

>>> f.func_defaults
([],)

これは、関数のデフォルト値を含むタプルです。デフォルト値がオブジェクトの場合、タプルにはそのオブジェクトのインスタンスが含まれます。

fこれは、リストに項目を追加し、リストが提供されていない場合にその項目のみを含むリストを返すことを考えている場合、かなり直感に反する動作につながります。

>>> f(1)
[1]
>>> f(2)
[1, 2]

しかし、デフォルト値が関数の属性の 1 つに格納されているオブジェクト インスタンスであることがわかっている場合は、それほど直感的ではありません。

>>> x = f(3)
>>> y = f(4)
>>> x == y
True
>>> x
[1, 2, 3, 4]
>>> x.append(5)
>>> f(6)
[1, 2, 3, 4, 5, 6]

これを知っていれば、関数のパラメーターのデフォルト値を新しいリスト (または任意の新しいオブジェクト) にしたい場合、単純にオブジェクトのインスタンスを に隠しておくことはできないことは明らかですfunc_defaults。関数が呼び出されるたびに新しいものを作成する必要があります。

>>>def g(x, y=None):
       if y==None:
           y = []
       y.append(x)
       return y
于 2009-10-18T17:10:36.050 に答える
15

次のことを行う必要があります。

class A:
    def __init__(self, builds=None):
        if builds is None:
            builds = B()
        self.builds = builds

これは、変更可能なパラメーターをデフォルトの引数として使用する、非常に広範囲に及ぶエラーです。おそらくSOにはたくさんのだまされています。

于 2009-10-18T16:11:36.923 に答える
6

はい; デフォルトのパラメーターは、関数が定義されたときにのみ評価されます。

考えられる解決策の 1 つは、パラメーターをインスタンスではなくクラスにすることです。

def foo(blah, klass = B):
    b = klass()
    # etc
于 2009-10-18T16:07:01.743 に答える