can*_*nin 5 python initialization list
我想创建一个类的实例,其中包含默认为空的列表; 而不是以后将此列表设置为最终完整列表,我想连续添加项目.这是一段示例代码,说明了这一点:
#!/usr/bin/python
class test:
def __init__(self, lst=[], intg=0):
self.lista = lst
self.integer = intg
name_dict = {}
counter = 0
for name in ('Anne', 'Leo', 'Suzy'):
counter += 1
name_dict[name] = test()
name_dict[name].integer += 1
name_dict[name].lista.append(counter)
print name, name_dict[name].integer, name_dict[name].lista
Run Code Online (Sandbox Code Playgroud)
当我运行上述程序时,我希望得到
安妮1 [1]
狮子座1 [2]
Suzy 1 [3]
因为我假设lista总是初始化为空列表.
我得到的是这样的:
安妮1 [1]
狮子座1 [1,2]
Suzy 1 [1,2,3]
如果我更换self.lista = lst由self.lista = []它工作正常,当我添加行就像name_dict[name].lista = []for循环.
为什么保留先前对象列表的内容,但它们的值integer不是?我对Python很陌生,所以如果有人可以向我指出我的想法/假设误入歧途,那将会很棒.
非常感谢您的回复.
Mar*_*ers 12
使用可变对象作为默认值是一个非常糟糕的主意,就像在这里一样:
def __init__(self, lst=[], intg=0):
# ...
Run Code Online (Sandbox Code Playgroud)
把它改成这个:
def __init__(self, lst=None, intg=0):
if lst is None:
lst = []
# ...
Run Code Online (Sandbox Code Playgroud)
您的版本不起作用的原因是在定义函数时只创建一次空列表,而不是每次调用函数时都创建.
在一些Python实现中,您可以通过检查以下值来func_defaults查看函数默认值的值:
print test.__init__.func_defaults
name_dict[name] = test()
# ...
Run Code Online (Sandbox Code Playgroud)
输出:
([],) Anne 1 [1] ([1],) Leo 1 [1, 2] ([1, 2],) Suzy 1 [1, 2, 3]
问题在于这一行:
def __init__(self, lst=[], intg=0):
Run Code Online (Sandbox Code Playgroud)
您不应该使用列表作为默认参数。第一次__init__在没有lst指定的情况下调用 Python 解释器将定义一个空列表[]。如果未指定,对该函数的后续调用将对同一列表进行操作lst,而不声明新列表。这会导致奇怪的问题。
您应该改为使用默认值None并在函数开头添加一个检查:
def __init__(self, lst=None, intg=0):
if lst is None:
lst = []
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅此帖子。引用帖子:
默认参数在函数定义时进行评估,因此它们在调用之间是持久的。这有一些有趣(且令人困惑)的副作用。一个例子:
>>> def foo(d=[]):
... d.append('a')
... return d
Run Code Online (Sandbox Code Playgroud)
如果你以前没有尝试过,你可能希望 foo 总是返回
['a']:它应该以一个空列表开始,在它后面附加 'a',然后返回。这是它的实际作用:
>>> foo() ['a']
>>> foo() ['a', 'a']
>>> foo() ['a', 'a', 'a']
Run Code Online (Sandbox Code Playgroud)
这是因为默认值
d是在创建函数时分配的,而不是在调用时分配的。每次调用该函数时,该值仍与上次调用有关。如果您将线程放入混合中,这会变得更加奇怪。如果两个不同的线程同时执行该函数,并且其中一个更改了默认参数,则它们都会看到更改。当然,所有这些只有在默认参数的值是可变类型时才成立。如果我们改变
foo为定义为
>>> def foo2(d=0):
... d += 1
... return d
Run Code Online (Sandbox Code Playgroud)
那么它将总是返回 1。(这里的区别在于
foo2,变量d被重新赋值,而变量foo的值被改变。)
| 归档时间: |
|
| 查看次数: |
11152 次 |
| 最近记录: |