Python:新的实例变量不是在新的类实例中创建的

时间:2013-03-11 16:19:36

标签: python inheritance initialization

我发现奇怪的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,但由于未知原因,它从前一个对象获取状态。为什么会这样?如何获得理想的行为?

谢谢!

2 个答案:

答案 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__