Python中的继承类变量修改

DMa*_*ack 53 python python-2.7

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

我想做一些事情:

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

class Child(Parent):
    # This does not work
    foobar = foobar.extend(["world"])
Run Code Online (Sandbox Code Playgroud)

理想情况下:

Child.foobar = ["hello", "world"]
Run Code Online (Sandbox Code Playgroud)

我可以:

class Child(Parent):
    def __init__(self):
      type(self).foobar.extend(["world"])
Run Code Online (Sandbox Code Playgroud)

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

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

但这仍然是一个黑客,因为我必须在它工作之前实例化一个Child实例.

有没有更好的办法?

小智 49

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

class Child(Parent):
    foobar = Parent.foobar + ['world']
Run Code Online (Sandbox Code Playgroud)

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

  • 这是非常精彩和简单的!另外,如果子属性的起始值必须与父属性相同,使用`from copy import deepcopy; foob​​ar = deepcopy(Parent.foobar)` (2认同)

Mar*_*ers 25

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

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

class Child(Parent):
    def __init__(self):
        super(Child, self).__init__()
        self.foobar.append('world')
Run Code Online (Sandbox Code Playgroud)

否则会发生的事情是,foobar列表不仅在实例之间共享,而且与子类共享.

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

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

class Child(Parent):
    foobar = Parent.foobar + ['world']
Run Code Online (Sandbox Code Playgroud)

为类创建一个 foobar变量的位置Child.通过使用赋值,您创建了一个新的列表实例,并且Parent.foobarmutable不受影响.

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