在python中继承和覆盖__init__

时间:2009-04-15 20:45:46

标签: python override superclass

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

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

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

  1. 如果FileInfo班级有多个祖先班级怎么办?
    • 我是否必须明确调用所有祖先类的__init__方法?
  2. 另外,我是否必须对要覆盖的任何其他方法执行此操作?

5 个答案:

答案 0 :(得分:142)

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

现在看起来像这样。

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

请注意以下事项。

  1. 我们可以直接对内置类进行子类化,例如dictlisttuple等。

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

答案 1 :(得分: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

答案 2 :(得分:14)

你真的没有来调用基类的__init__方法,但你通常想要来做它,因为基础类将在那里进行一些重要的初始化,这些初始化是其他类方法工作所必需的。

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

答案 3 :(得分:4)

如果FileInfo类有多个祖先类,那么你一定要调用它们的所有__init __()函数。你也应该为__del __()函数做同样的事情,它是一个析构函数。

答案 4 :(得分:2)

是的,您必须为每个父类调用__init__。如果要覆盖父母双方都存在的功能,那么功能也是如此。