Python的可选参数(Python optional parameters)

2019-08-20 01:25发布

伙计们,我刚开始蟒蛇最近和感到困惑与可选参数,说我有一个这样的程序:

class B:
   pass

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

如果我创建一个两次

b = A()
c = A()

和打印他们的建立

print b.builds
print c.builds

我发现,他们使用的是完全相同的对象,

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

但它不是我想要的,因为如果b改变建立的一些内部状态,一个在c对象也随之发生变化。

是否有可能通过使用此可选参数语法每次重新创建可选参数?

Answer 1:

你需要了解的默认值,以便有效地使用它们是如何工作的。

函数是对象。 因此,他们的属性。 所以,如果我创建这个函数:

>>> 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']

其中之一是func_defaults 。 这听起来有希望的,什么是在那里呢?

>>> f.func_defaults
([],)

这是一个包含了函数的默认值的元组。 如果默认值是一个对象,元组包含对象的实例。

这导致了一些非常违反直觉的行为,如果你在想那f增加了一个项目列表,返回只包含项目的列表,如果没有提供列表:

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

但是,如果你知道默认值是一个储存在该函数的属性之一的对象实例,这是更有悖常理:

>>> 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


Answer 2:

你需要做到以下几点:

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

这是一个非常广泛的传播错误,使用可变参数的默认参数。 有很多愚弄的可能对SO。



Answer 3:

是; 仅在当所定义的功能的时间的默认参数进行评估。

一个可能的解决办法是有参数是一个而不是一个实例,一拉

def foo(blah, klass = B):
    b = klass()
    # etc


文章来源: Python optional parameters