将列表传递给Python类

6

我有一个简单的类:

class revs:
    def __init__(self, rev, us, accs = []):
        self.rev = rev
        self.us = us
        self.accs = accs

我有这段代码来为列表分配值,并且它在一个循环内:

rev, usu = cada_l.split("|")
acct = each_l[:2].strip()
list_acct.append(acct)

最后,我创建了一个字典,来管理类似这样的修订版本列表:
drevs = {}
cada = revs(rev, us, list_acct)
drevs[cada.rev] = cada

它与rev和us正确地工作,但与list_acct一起,它会不断更新所有实例:

drevs['1'].rev
'1'
drevs['2'].rev
'2'
drevs['1'].us
'user1'
drevs['2'].us
'user2'
drevs['1'].accs
'["Doc1","Doc2"]'
drevs['2'].accs
'["Doc1","Doc2"]'

如果我使用list_acct.clear()进行清空,所有实例中的值都会被清空。作为Python新手,这让我感到困惑。

谢谢


1
将默认值 accs 设为 None,并在 __init__ 中检查它。 - voithos
1个回答

8
这似乎是因为您将同一个列表传递给每个对象。结果,所有对象都保持对同一列表的引用,并且由于 list 是可变的,因此它似乎同时更改了“所有”对象。
要解决此问题,请每次创建 revs 对象时传入一个的空列表,或者克隆您正在传递的列表:
cada = revs(rev, us, list_acct[:])

请注意,如果list_acct包含可变对象,则可能会再次遇到相同的问题,但深度更深!
如果您在创建revs对象时根本没有传递列表(我无法确定,因为您未显示完整的代码!),那么您将面临相同的问题,但原因不同:在Python中,默认参数都在函数定义时执行一次。因此,您可能会遇到这种行为:
r1 = revs(1, 1)
r2 = revs(2, 2)
r1.accs.append("Hi!")
print(r1.accs) # prints ['Hi!']
print(r2.accs) # prints ['Hi!']

因为revs构造函数的默认参数总是指向同一个列表。有关原因的解释,请参见this question,但要避免这种情况,只需将[]替换为None作为您的默认值即可。
class revs:
    def __init__(self, rev, us, accs=None):
        self.rev = rev
        self.us = us
        if accs is None:
            accs = []
        self.accs = accs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接