use*_*048 24 python optional-arguments
伙计们,我刚刚开始使用python并且对可选参数感到困惑,比如我有这样的程序:
class B:
pass
class A:
def __init__(self, builds = B()):
self.builds = builds
Run Code Online (Sandbox Code Playgroud)
如果我创建A两次
b = A()
c = A()
Run Code Online (Sandbox Code Playgroud)
并打印他们的构建
print b.builds
print c.builds
Run Code Online (Sandbox Code Playgroud)
我发现他们正在使用完全相同的对象,
<__main__.B instance at 0x68ee0>
<__main__.B instance at 0x68ee0>
Run Code Online (Sandbox Code Playgroud)
但它不是我想要的,因为如果b改变一些内部构建状态,c对象中的那个也将被改变.
是否可以通过使用此可选参数语法每次重新创建此可选参数?
Rob*_*ney 47
您需要了解默认值的工作原理才能有效地使用它们.
功能是对象.因此,他们有属性.所以,如果我创建这个函数:
>>> def f(x, y=[]):
y.append(x)
return y
Run Code Online (Sandbox Code Playgroud)
我创造了一个物体.这是它的属性:
>>> 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']
Run Code Online (Sandbox Code Playgroud)
其中之一是func_defaults.听起来很有希望,那里有什么?
>>> f.func_defaults
([],)
Run Code Online (Sandbox Code Playgroud)
这是一个包含函数默认值的元组.如果默认值是对象,则元组包含该对象的实例.
如果您考虑f将项添加到列表中,如果没有提供列表,则返回仅包含该项的列表,这会导致一些相当违反直觉的行为:
>>> f(1)
[1]
>>> f(2)
[1, 2]
Run Code Online (Sandbox Code Playgroud)
但是,如果您知道默认值是存储在函数属性之一中的对象实例,那么它就不那么违反直觉了:
>>> 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]
Run Code Online (Sandbox Code Playgroud)
知道了这一点,很明显,如果你想要一个函数参数的默认值是一个新的列表(或任何新的对象),你不能简单地存储该对象的实例func_defaults.每次调用函数时都必须创建一个新的:
>>>def g(x, y=None):
if y==None:
y = []
y.append(x)
return y
Run Code Online (Sandbox Code Playgroud)
Sil*_*ost 15
你需要做以下事情:
class A:
def __init__(self, builds=None):
if builds is None:
builds = B()
self.builds = builds
Run Code Online (Sandbox Code Playgroud)
这是一个非常广泛的错误,使用可变参数作为默认参数.SO上有很多傻瓜.
是; 仅在定义函数时评估默认参数.
一种可能的解决方案是将参数设为类而不是实例,即la
def foo(blah, klass = B):
b = klass()
# etc
Run Code Online (Sandbox Code Playgroud)