我有以下三个班级:
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
执行相同的操作。
我不明白的两件事:
为什么我必须将参数传递给super.__init__
中的Page
,而Page
只是要调用__init__
它继承自object
。
为什么我不必为Report
做同样的事情。
答案 0 :(得分:6)
super()
查看当前实例的MRO。在这里,当前的 class 仅从object
继承即可。
ReportingPage
的MRO将Report
放在Page
和object
之间:
>>> ReportingPage.__mro__
(<class '__main__.ReportingPage'>, <class '__main__.Page'>, <class '__main__.Report'>, <class 'object'>)
因此,当您在super()
中调用Page.__init__()
时,MRO中的下一个类是Report
,最终您会调用Report.__init__
方法。
您需要使您的班级更加合作;您可以使用关键字参数和全面的**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__()
。如果将print(kwargs)
包装器添加到每个__init__
方法中,则可以看到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's super considered super感兴趣,包括他的PyCon 2015 presentation。