75

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

我想做一些类似的事情:

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"])

但这仍然是一个hack,因为我必须在它工作之前实例化一个 Child 的实例。

有没有更好的办法?

4

3 回答 3

76

假设您想在子类中有一个单独的列表,而不是修改父类的列表(这似乎毫无意义,因为您可以将其修改到位,或者将预期值放在那里):

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

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

于 2012-11-15T19:16:55.170 回答
39

你不应该在你的类变量中使用可变值。而是使用实例初始化器在实例上设置此类值:__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变量Child。通过使用赋值,您创建了一个新的列表实例,并且Parent.foobar可变变量不受影响。

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

于 2012-11-15T19:15:14.563 回答
-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?']
于 2020-10-16T01:04:38.340 回答