我已经多次阅读the documentation for super()
但我仍然没有得到两个参数版本返回的内容。
返回将方法调用委托给父或者的代理对象 兄弟类的类型。这对于访问继承的方法很有用 在课堂上被覆盖的。
如果第二个参数是一个对象,
isinstance(obj, type)
必须是 真正。如果第二个参数是类型,则issubclass(type2, type)
必须 是真的(这对于类方法很有用。)
super(a,b)
意味着是什么意思? 在__new__
,
典型实现通过调用创建类的新实例 超类的__new __()方法使用
super(currentclass, cls).__new__(cls[, ...])
和适当的参数然后修改 在返回之前必要时新创建的实例。
super(currentclass, cls).__new__(cls[, ...])
如果currentclass
等于cls
,则您有super(currentclass, currentclass)
cls
的实例,以便在返回的对象上调用__init__
?答案 0 :(得分:2)
“super
返回的内容”的答案不是“它返回列表”或“它返回第二个对象的修改后的副本”。 super
返回super
类型的对象,该类型专门设计为具有文档所具有的品质。
也许有助于展示super
的纯Python实现。如果super
没有用C语言编写,它看起来基本上就是这样:
class super(object):
def __init__(self, klass, object_or_klass):
# The real super can be called with 0 arguments on Python 3,
# but digging into the magic that makes that work isn't relevant here.
if isinstance(object_or_klass, klass):
mro = type(object_or_klass).__mro__
self.obj_type = type(object_or_klass)
self.obj = object_or_klass
elif issubclass(object_or_klass, klass):
mro = object_or_klass.__mro__
self.obj_type = object_or_klass
self.obj = None
else:
raise TypeError
# Set up a copy of the MRO to search,
# with everything up to and including klass skipped
self.searchlist = mro[mro.index(klass)+1:]
def __getattribute__(self, name):
# self.searchlist would be infinite recursion, as would super().__getattribute__
searchlist = object.__getattribute__(self, 'searchlist')
# Search the method resolution order for the attribute we want.
for klass in searchlist:
if name in klass.__dict__:
attr = klass.__dict__[name]
break
else:
raise AttributeError
if hasattr(attr, '__get__'):
# Handle descriptors.
obj = object.__getattribute__(self, 'obj')
obj_type = object.__getattribute__(self, 'obj_type')
attr = attr.__get__(obj, obj_type)
return attr
现在您可以看到super(a, b)
构建了一个super
对象,super(a, b).whatever
调用了该__getattribute__
对象的super
方法来搜索方法解析顺序我们想要的属性的第二个参数。 b.whatever
的属性查找过程非常相似,只是没有删除MRO的第一部分,并检查实例dict b
是否不是类。
答案 1 :(得分:-1)
你应该肯定观看Raymond Hettinger在PyCon 2015上的演讲,Super is considered super!
但如果没有,为什么不添加一堆打印陈述来回答你的问题?
# (object) is only required in Python2
class Mom(object):
def __init__(self, *args, **kwargs):
print('Mom is initializing - args: {!r} kwargs: {!r}'.format(
args, kwargs))
def do_something(self):
print('Doing some Mom thing')
class Dad(object):
def __init__(self, *args, **kwargs):
print('Dad is initializing - args: {!r} kwargs: {!r}'.format(
args, kwargs))
def do_something(self):
print('Doing some Dad thing')
class Sister(Mom, Dad):
def __init__(self, name):
print('initializing a Sister with name: {!r}'.format(name))
parent = super(Sister, self)
print(type(parent))
print(parent)
print('Calling super __init__')
parent.__init__(name)
def do_something(self, value):
if value == 5:
print('calling method on super')
super(Sister, self).do_something()
else:
print('Sister did something')
class Brother(Mom):
def __init__(self, name):
print('initializing a Brother with name: {!r}'.format(name))
parent = super(Brother, self)
print(type(parent))
print(parent)
print('Calling super __init__')
parent.__init__(name)
def do_something(self, value):
if value == 5:
print('calling method on super')
super(Brother, self).do_something()
else:
print('Brother did something')
b = Brother('Bear')
s = Sister('Moon')
b.do_something(3)
b.do_something(5)
s.do_something(3)
s.do_something(5)
产生以下输出(附加评论):
<type 'super'>
<super: <class 'Brother'>, <Brother object>>
Calling super __init__
Mom is initializing - args: ('Bear',) kwargs: {}
显然,super
会返回super
类的类。根据文档,这是一个代理对象。根据定义,代理是其他东西的替代品。在这种情况下,代理是获取Mom
的替代品。你可以看到,当我们实际调用__init__
函数时,会调用Mom的init函数。
initializing a Sister with name: 'Moon'
<type 'super'>
<super: <class 'Sister'>, <Sister object>>
Calling super __init__
Mom is initializing - args: ('Moon',) kwargs: {}
你会注意到,没有调用爸爸的init函数。那是因为,如果你看雷蒙德的谈话,你会知道super
从左到右寻找父母的功能。
Brother did something
calling method on super
Doing some Mom thing
您在此处重复了相同的行为
Sister did something
calling method on super
Doing some Mom thing
如果您将姐妹的订单更改为Dad, Mom
,您会看到这些来电更改:
initializing a Brother with name: 'Bear'
<type 'super'>
<super: <class 'Brother'>, <Brother object>>
Calling super __init__
Mom is initializing - args: ('Bear',) kwargs: {}
initializing a Sister with name: 'Moon'
<type 'super'>
<super: <class 'Sister'>, <Sister object>>
Calling super __init__
Dad is initializing - args: ('Moon',) kwargs: {}
Brother did something
calling method on super
Doing some Mom thing
Sister did something
calling method on super
Doing some Dad thing
总结一下:
代理是代替其他东西的东西。在我们的案例中,super
是妈妈和妈妈的代理人。爸爸,取决于他们继承的顺序。
老实说,我无法找到任何有意义的兄弟姐妹的事情。我不确定你什么时候甚至不需要它。
返回super
的实例。
如果你有从type
继承的东西,那就真的有效。 super(type, type)
,因为您需要该类型的实例。 object
也可以,因为:
print(isinstance(object,object)) print(isinstance(type,type)) print(isinstance(object,type)) print(isinstance(type,object))
围绕 进程有一些非常复杂的魔法。
object.__new__
会返回一些内容。我不确定该函数的实际源代码在哪里,或者如果您对确切的机制感兴趣,我可以指出那里。