【问题标题】:Inherited class variable modification in PythonPython中的继承类变量修改
【发布时间】:2012-11-04 11:07:15
【问题描述】:

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

我想做一些类似的事情:

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 的实例才能工作。

有没有更好的办法?

【问题讨论】:

    标签: python python-2.7


    【解决方案1】:

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

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

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

    【讨论】:

    • 这简直太棒了!此外,如果子属性的起始值必须与父属性相同,则使用from copy import deepcopy; foobar = deepcopy(Parent.foobar) 会有所帮助
    • 如果你使用列表理解,你可以达到与 deepcopy 相同的效果:[foo for foo in Parent.foobar] + ['world]
    【解决方案2】:

    您不应在类变量中使用可变值。而是使用__init__() 实例初始化程序在 instance 上设置此类值:

    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']
    

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

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

    【讨论】:

      【解决方案3】:

      将参数传递给__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?']
      

      【讨论】:

        猜你喜欢
        • 2018-02-24
        • 2013-02-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-16
        • 2021-04-10
        相关资源
        最近更新 更多