继承+类成员

时间:2011-09-13 21:37:48

标签: python oop inheritance

我从Python开始并遇到了这种奇怪的行为(至少对我而言):

class Parent:
    myStr = ""
    myInt = 0
    myDict = {}
    ....

class ChildA:
    ...
    def ...():
        self.myDict.<something>(...)
        print self.myStr
    ...

class ChildB:
    ...
    def ...():
        self.myDict.<something>(...)
        print self.myStr
    ...

根据我的理解,ChildA和ChildB的实例应该有自己的词典。但事实证明,他们“共享”字典。要修复它,我需要在父的构造函数中设置self.myDict = {}。另一方面,myStr和myInt似乎有其预期的值。为什么会这样?

4 个答案:

答案 0 :(得分:3)

这是因为在类级别绑定的名称属于该类,而不属于任何实例。因此,所有myDict都是相同的词。由于dict实例是可变的,因此通过一个类/实例引用所做的更改将显示在所有实例中。字符串和数字是不可变的,因此当通过子类或实例分配时,它们会反弹。

答案 1 :(得分:3)

myDict是类级别的,因此当Python查看实例并且找不到它时,它会搜索继承树,直到它为止。如果在实例中的任何位置重新绑定名称myDict,则实例将具有自己的版本。

使用dictlist等可变对象时很容易看到此行为,但使用strint等不可变对象更难以观察到,tuple等,因为为了“改变”不可变的值,你必须重新绑定名称 - 如下所示:

class Foo(object):
    collection = list()
    number = 9
    def change_collection(self, new_member):
        self.collection.append(new_member)
    def change_number(self, new_number):
        self.number = new_number

a = Foo()
b = Foo()
a.change_collection('howdy!')
b.change_number(11)
print a.collection, b.collection     # ['howdy!]  ['howdy!']
print a.number, b.number             # 9  11
print a.collection is b.collection   # True
print a.number is b.number           # False

答案 2 :(得分:2)

这是因为在级别设置myDict会将其绑定到类和而不是类的实例(即,所有实例将共享相同的myDict)。

答案 3 :(得分:0)

问题的关键在于Ignacio指出,可变与不可变。这是一个完整的ASCII图解释的链接:

http://mail.python.org/pipermail/tutor/2001-February/003787.html