我有如下三个类:
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
只是调用__init__
它继承自object
。为什么我不必为
Report
做同样的事情。
最佳答案
super()
查看当前实例 的 MRO。当前 class 仅继承自 object
在这里并不重要。
ReportingPage
的 MRO 将 Report
放在 Page
和 object
之间:
>>> ReportingPage.__mro__
(<class '__main__.ReportingPage'>, <class '__main__.Page'>, <class '__main__.Report'>, <class 'object'>)
所以当你在 Page.__init__()
中调用 super()
时,MRO 中的下一个类是 Report
,你结束向上调用 Report.__init__
方法。
你需要让你的类(class)更加合作;你可以使用关键字参数和一个包罗万象的 **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 .
关于python - 在 Python 中使用 super(),我不明白最后一次调用 __init__,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50953637/