问题:在python中继承和覆盖__init__

我正在阅读“深入Python”,并在有关类的章节中给出了以下示例:

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

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

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

I was reading ‘Dive Into Python’ and in the chapter on classes it gives this example:

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

The author then says that if you want to override the __init__ method, you must explicitly call the parent __init__ with the correct parameters.

  1. What if that FileInfo class had more than one ancestor class?
    • Do I have to explicitly call all of the ancestor classes’ __init__ methods?
  2. Also, do I have to do this to any other method I want to override?

回答 0

关于子类-超类调用,这本书有些过时了。在子类化内置类方面也有些过时。

如今看起来像这样:

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

请注意以下几点:

  1. 我们可以直接继承内建类,如dictlisttuple,等。

  2. super函数负责跟踪此类的超类并在其中适当地调用函数。

The book is a bit dated with respect to subclass-superclass calling. It’s also a little dated with respect to subclassing built-in classes.

It looks like this nowadays:

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

Note the following:

  1. We can directly subclass built-in classes, like dict, list, tuple, etc.

  2. The super function handles tracking down this class’s superclasses and calling functions in them appropriately.


回答 1

在您需要继承的每个类中,您可以运行每个需要在子类启动时进行初始化的类的循环…可以更好地理解可以复制的示例…

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

In each class that you need to inherit from, you can run a loop of each class that needs init’d upon initiation of the child class…an example that can copied might be better understood…

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

您实际上不必调用__init__基类的方法,但是通常您希望这样做,因为基类将在其中进行一些重要的初始化,而其余的类方法都需要进行初始化。

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

You don’t really have to call the __init__ methods of the base class(es), but you usually want to do it because the base classes will do some important initializations there that are needed for rest of the classes methods to work.

For other methods it depends on your intentions. If you just want to add something to the base classes behavior you will want to call the base classes method additionally to your own code. If you want to fundamentally change the behavior, you might not call the base class’ method and implement all the functionality directly in the derived class.


回答 3

如果FileInfo类具有多个祖先类,则您绝对应该调用其所有__init __()函数。您还应该对__del __()函数(该函数是析构函数)执行相同的操作。

If the FileInfo class has more than one ancestor class then you should definitely call all of their __init__() functions. You should also do the same for the __del__() function, which is a destructor.


回答 4

是的,您必须调用__init__每个家长班。如果要覆盖两个父级中都存在的功能,则功能也是如此。

Yes, you must call __init__ for each parent class. The same goes for functions, if you are overriding a function that exists in both parents.


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。