我想让子类修改它从父类继承的类变量。
我想按照以下方式做点什么:
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实例。
有更好的方法吗?
答案 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?']