我发现奇怪的Python行为(或者我可能不理解属性的继承和/或默认值是如何工作的。)
对于给定的代码
class A(object):
def __init__(self, s):
self.s = s
print "in init", self.s
class B(A):
def __init__(self, s = set()):
super(B, self).__init__(s)
print "after super", self.s
self.s.add('foo')
print '--------------'
if __name__ == "__main__":
a = B()
b = B()
我得到以下输出:
in init set([])
after super set([])
--------------
in init set(['foo']) # Why it has value set in other object?!
after super set(['foo'])
--------------
当然,期望的行为是使用空集在第二个对象(b)中初始化self,但由于未知原因,它从前一个对象获取状态。为什么会这样?如何获得理想的行为?
谢谢!
答案 0 :(得分:8)
你已成为可变默认参数陷阱的牺牲品。您在B set()
中指定为默认值的__init__
与传递给您创建的每个新B
的对象相同。将它放入self
不会创建新副本,它只是创建对同一对象的引用。
您可能希望在每个新对象中制作副本,因此请明确地执行此操作:
class A(object):
def __init__(self, s):
self.s = copy.copy(s)
答案 1 :(得分:0)
为参数设置默认值时,将在定义函数时计算该值,而不是在调用时计算。因此,它使用了在您定义类时创建的set()
,并添加了越来越多的项目。
相反,典型的Python模式是使用None
作为默认值,然后在{{{{{}体内显式初始化新的set()
(或列表,dict或任何对象)。 1}}。
__init__