[英]Python convention: should I normally call the super class' __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:
首先調用Page
對象,因為它首先在ReportingPage
的繼承列表中排序,它在其中調用自己的__init__
方法。
然后它對Report
。
我不明白的兩件事:
為什么我必須將參數傳遞給Page
的super.__init__
,當Page
只是在它繼承的object
上調用__init__
時。
為什么我不必為Report
做同樣的事情。
super()
查看當前實例的MRO。 這里的當前類只從object
繼承並不重要。
ReportingPage
的MRO在Page
和object
之間放置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.