Python中的继承类变量修改

时间:2012-11-15 19:12:25

标签: python python-2.7

我想让子类修改它从父类继承的类变量。

我想按照以下方式做点什么:

class Parent(object):
    foobar = ["hello"]

class Child(Parent):
    # This does not work
    foobar = foobar.extend(["world"])

理想情况下:

Child.foobar = ["hello", "world"]

我能做到:

class Child(Parent):
    def __init__(self):
      type(self).foobar.extend(["world"])

但是每当我实例化Child的一个实例时,“world”会被附加到列表中,这是不希望的。我可以进一步修改它:

class Child(Parent):
    def __init__(self):
      if type(self).foobar.count("world") < 1:
          type(self).foobar.extend(["world"])

但这仍然是一个黑客攻击,因为我必须在它运行之前实例化一个Child实例。

有更好的方法吗?

3 个答案:

答案 0 :(得分:49)

假设您希望在子类中有一个单独的列表,而不是修改父类的列表(这似乎没有意义,因为您可以在适当的位置修改它,或者将预期的值放在那里开始):

class Child(Parent):
    foobar = Parent.foobar + ['world']

请注意,这与继承无关,这可能是一件好事。

答案 1 :(得分:23)

您不应在类变量中使用可变值。使用__init__()实例初始值设定项在实例上设置此类值:

class Parent(object):
    def __init__(self):
        self.foobar = ['Hello']

class Child(Parent):
    def __init__(self):
        super(Child, self).__init__()
        self.foobar.append('world')

否则会发生什么,foobar列表不仅在实例之间共享,还与子类共享。

在任何情况下,即使您希望通过可变类变量在实例之间共享状态,您也必须避免修改父类的可变项;只有赋值到一个名称才会创建一个新变量:

class Parent(object):
    foobar = ['Hello']

class Child(Parent):
    foobar = Parent.foobar + ['world']

其中为foobar类创建了 new Child变量。通过使用赋值,您创建了一个新的列表实例,Parent.foobar mutable不受影响。

在这种情况下,请注意嵌套的mutable;如有必要,使用copy模块创建深层副本。

答案 2 :(得分:-1)

将参数传递给__init__('world')使其更加清晰:

class Parent():
    def __init__(self):
        self.foobar = ['Hello']

class Child(Parent):
    def __init__(self, h):
        super().__init__()
        self.foobar.append(h)

g = Child('world')
print(f'g.foobar = {g.foobar}')
p = Child('how are you?')
print(f'p.foobar = {p.foobar}')

输出:

g.foobar = ['Hello', 'world']
p.foobar = ['Hello', 'how are you?']