Python 父类、子类的数据掺杂到一起了?

来源:互联网 发布:淘宝店铺活动图片 编辑:程序博客网 时间:2024/05/01 15:40

以此为例:

class A:

    attr_list = []

    def  __init__(self, attr_list = []):

        self.attr_list = attr_list

    def __del__(self):

        del self.attr_list[:]

    def addAttr(self, attr):

        self.attr_list.append(attr)

class B(A):

    def __init__(self):

        pass

class C(A):

    def __init__(self):

        pass

b = B()

c = C()

b.addAttr(1)

c.addAttr(2)

for attr in b.attr_list:

    print attr ## 此处输出1,2

for attr in c.attr_list:

    print attr  ## 此处也输出1,2

奇怪了,从基类A派生出两个不同的子类B、C,分别定义了一个实例b、c并各自添加数据1、2,怎么会导致两个实例中的数据都是1,2呢?难道他们用的是一个地址?好说,来,来验证一下!

print id(b.attr_list)

print id(c.attr_list)

打印出来的两个地址果然是一样的,原来如此!那为什么会这样呢?

仔细看,才发现原因出在A中attr_list定义的位置不对,对python而言,在类名和__init__之前定义的变量(注意,这时候是不能用self的,因为不识别),是类全局的, 可以认为和C++类中的静态变量等价,这样就可以解释了。

那究竟应该怎么定义类的普通变量呢?简单,在__init__函数中,使用self来定义就OK了,改造如下:

class A:   ##不要在此处和__init__之间定义普通变量,除非你真的想用它做静态变量,否则。。。

    def __init__(self, attr_list = []):

        self.attr_list = attr_list

而且还有一个注意点,子类B、C的__init__函数中,首行就应该先调用父类A的__init__函数,__del__如是。

改造如下:

class A:

    def __init__(self, attr_list = []):

        self.attr_list = attr_list

    def __del__(self):

        del self.attr_list[:]

    def addAttr(self, attr):

        self.attr_list.append(attr)

class B(A):

    def __init__(self):

        A.__init__(self)

class C(A):

    def __init__(self):

        A.__init__(self)

再次分别声明变量b、c并添加1、2,打印出来看看,哈哈,果然分开了,分别是1、2.

看来还是自己对python的机制理解不够,导致出现这种使用问题,不过吃一堑长一智,还是很幸运。