在python中继承和覆盖__init__

lie*_*ewl 124 python overriding superclass

我正在阅读'Dive Into Python',并在关于类的章节中给出了这个例子:

class FileInfo(UserDict):
    "store file metadata"
    def __init__(self, filename=None):
        UserDict.__init__(self)
        self["name"] = filename
Run Code Online (Sandbox Code Playgroud)

然后,作者说如果要覆盖该__init__方法,则必须__init__使用正确的参数显式调用父级.

  1. 如果那个FileInfo班有一个以上的祖先课怎么办?
    • 我是否必须显式调用所有祖先类的__init__方法?
  2. 另外,我是否必须对我想要覆盖的任何其他方法执行此操作?

S.L*_*ott 149

这本书对于子类 - 超类调用有点过时了.对于子类内置类,它也有点过时了.

现在看起来像这样.

class FileInfo(dict):
    """store file metadata"""
    def __init__(self, filename=None):
        super(FileInfo, self).__init__()
        self["name"] = filename
Run Code Online (Sandbox Code Playgroud)

请注意以下内容.

  1. 我们可以直接继承内建类,如dict,list,tuple,等.

  2. super函数处理跟踪此类的超类并适当调用其中的函数.

  • 我应该寻找更好的书/教程吗? (5认同)
  • super()的意图是它处理多重继承.缺点是,在实践中,多继承仍然很容易破坏(参见<http://fuhm.net/super-harmful/). (4认同)
  • 因此,在多重继承的情况下,super()是否代表您全部跟踪它们? (2认同)
  • dict .__ init __()究竟有什么问题? (2认同)
  • 是的,如果多继承和基类采用构造函数参数,您通常会发现自己手动调用构造函数. (2认同)

小智 16

在您需要继承的每个类中,您可以在启动子类时运行需要init'd的每个类的循环...可以更好地理解可以复制的示例...

class Female_Grandparent:
    def __init__(self):
        self.grandma_name = 'Grandma'

class Male_Grandparent:
    def __init__(self):
        self.grandpa_name = 'Grandpa'

class Parent(Female_Grandparent, Male_Grandparent):
    def __init__(self):
        Female_Grandparent.__init__(self)
        Male_Grandparent.__init__(self)

        self.parent_name = 'Parent Class'

class Child(Parent):
    def __init__(self):
        Parent.__init__(self)
#---------------------------------------------------------------------------------------#
        for cls in Parent.__bases__: # This block grabs the classes of the child
             cls.__init__(self)      # class (which is named 'Parent' in this case), 
                                     # and iterates through them, initiating each one.
                                     # The result is that each parent, of each child,
                                     # is automatically handled upon initiation of the 
                                     # dependent class. WOOT WOOT! :D
#---------------------------------------------------------------------------------------#



g = Female_Grandparent()
print g.grandma_name

p = Parent()
print p.grandma_name

child = Child()

print child.grandma_name
Run Code Online (Sandbox Code Playgroud)

  • 似乎不需要 `Child.__init__` 中的 for 循环。当我从示例中删除它时,我的孩子仍然打印“奶奶”。祖父母 init 不是由 `Parent` 类处理的吗? (3认同)
  • 我认为granparents init已经由Parent的init处理,不是吗? (3认同)

sth*_*sth 14

您实际上不必调用__init__基类的方法,但是您通常希望这样做,因为基类将在那里进行一些重要的初始化,这是其他类方法工作所需要的.

对于其他方法,它取决于您的意图.如果您只想在基类行为中添加一些内容,则需要在自己的代码之外调用基类方法.如果要从根本上改变行为,可能不会调用基类的方法并直接在派生类中实现所有功能.

  • 我发现所有这些"你没有必要打电话给基地的建设者"谈话非常烦人.你不必用我认识的任何语言来称呼它.通过不初始化成员,所有这些都会以相同的方式搞砸(或不是).建议不要在很多方面初始化基类是错误的.如果一个类现在不需要初始化,将来它将需要它.构造函数是类结构/语言构造的接口的一部分,应该正确使用.它的正确用法是在你的派生构造函数中调用它.这样做吧. (5认同)
  • 对于技术完整性,如果你试图避免调用父级的__init__,某些类,如threading.Thread,会抛出巨大的错误. (4认同)
  • “在许多方面,建议不初始化基类只是错误的。” 没有人建议不要初始化基类。仔细阅读答案。一切都与意图有关。1)如果您希望保持基类的初始化逻辑不变,则不要在派生类中重写init方法。2)如果要从基类扩展init逻辑,则定义自己的init方法,然后从中调用基类的init方法。3)如果要替换基类的init逻辑,请定义自己的init方法,而不要从基类中调用该方法。 (2认同)