簡體   English   中英

在Python中使用super(),我不理解最后一次__init__調用

[英]Using super() in Python, I do not understand this last __init__ call

我有三個課程如下:

class Page(object):
    def __init__(self, Obj_a, Obj_b):
        super().__init__(Obj_a, Obj_b)

class Report(object):
    def __init__(self, Obj_a, Obj_b):
        super().__init__()

class ReportingPage(Page,Report):
    def __init__(self, Obj_a, Obj_b):
        super().__init__(Obj_a, Obj_b)

我實例化一個ReportingPage對象。 要做到這一點,Python爬行MRO:

  1. 首先調用Page對象,因為它首先在ReportingPage的繼承列表中排序,它在其中調用自己的__init__方法。

  2. 然后它對Report

我不明白的兩件事:

  1. 為什么我必須將參數傳遞給Pagesuper.__init__ ,當Page只是在它繼承的object上調用__init__時。

  2. 為什么我不必為Report做同樣的事情。

super()查看當前實例的MRO。 這里的當前只從object繼承並不重要。

ReportingPage的MRO在Pageobject之間放置Report

>>> ReportingPage.__mro__
(<class '__main__.ReportingPage'>, <class '__main__.Page'>, <class '__main__.Report'>, <class 'object'>)

所以當你在Page.__init__()調用super() ,MRO中的下一個類是Report ,你最終調用Report.__init__方法。

你需要讓你的課程更合作; 你可以使用關鍵字參數和一個catch-all **kwargs參數來做到這一點:

class Page(object):
    def __init__(self, pagenum, **kwargs):
        self.pagenum = pagenum
        super().__init__(**kwargs)

class Report(object):
    def __init__(self, title, **kwargs):
        self.title = title
        super().__init__(**kwargs)

class ReportingPage(Page, Report):
    def __init__(self, footer=None, **kwargs):
        self.footer = footer
        super().__init__(**kwargs)

每個方法都將其余的關鍵字參數傳遞給MRO中的下一個__init__ ,最后你將有一個空字典傳遞給object.__init__() 如果為每個__init__方法添加一個print(kwargs)包裝器,您可以看到kwargs變小,因為下一個調用傳遞的值越來越少。

>>> def print_wrapper(name, f):
...     def wrapper(*args, **kwargs):
...         print(name, '->', kwargs)
...         return f(*args, **kwargs)
...     return wrapper
...
>>> for cls in ReportingPage.__mro__[:-1]:  # all except object
...     cls.__init__ = print_wrapper(cls.__name__, cls.__init__)
...
>>> ReportingPage(title='Watching Paint Dry II: The Second Coat', pagenum=42)
ReportingPage -> {'title': 'Watching Paint Dry II: The Second Coat', 'pagenum': 42}
Page -> {'title': 'Watching Paint Dry II: The Second Coat', 'pagenum': 42}
Report -> {'title': 'Watching Paint Dry II: The Second Coat'}
<__main__.ReportingPage object at 0x109e3c1d0>

只有title仍然存在, Report.__init__()消耗,因此將空的kwargs字典傳遞給object.__init__()

您可能對Raymond Hettinger的超級考慮超級感興趣,包括他的PyCon 2015演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM