Mat*_*ner 41 python multiple-inheritance python-2.x super python-3.x
经常声明在Python 2 中super
应该避免使用.我super
在Python 2中使用它发现它永远不会按照我的预期行事,除非我提供所有参数,例如:
super(ThisClass, self).some_func(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
在我看来,这违背了使用的目的super()
,它既不简洁,也不比它更好TheBaseClass.some_func(self, *args, **kwargs)
.在大多数情况下,方法解析顺序是一个遥远的童话故事.
super
要继续使用?Sve*_*ach 42
super()
没有被破坏 - 它不应该被认为是调用基类方法的标准方法.这与Python 3.x没有变化.唯一改变的是你不需要传递self, cls
标准情况下self
的参数,这是当前函数的第一个参数,并且cls
是当前正在定义的类.
关于你何时实际使用的问题super()
,我的回答是:几乎没有.我个人试图避免那种super()
有用的多重继承.
编辑:我曾经遇到的现实生活中的一个例子:我有一些定义run()
方法的类,其中一些有基类.我曾经super()
调用继承的构造函数 - 我认为它不重要因为我只使用单继承:
class A(object):
def __init__(self, i):
self.i = i
def run(self, value):
return self.i * value
class B(A):
def __init__(self, i, j):
super(B, self).__init__(i)
self.j = j
def run(self, value):
return super(B, self).run(value) + self.j
Run Code Online (Sandbox Code Playgroud)
想象一下,这些类中有几个,都有单独的构造函数原型,并且都具有相同的接口run()
.
现在我想为所有这些类添加一些额外的功能,比如记录.例如,附加功能需要在所有这些类上定义另一种方法info()
.我不想入侵原始类,而是定义继承自原始类的第二组类,添加info()
方法并从提供实际日志记录的混合继承.现在,我不能再super()
在构造函数中使用了,所以我使用了直接调用:
class Logger(object):
def __init__(self, name):
self.name = name
def run_logged(self, value):
print "Running", self.name, "with info", self.info()
return self.run(value)
class BLogged(B, Logger):
def __init__(self, i, j):
B.__init__(self, i, j)
Logger.__init__("B")
def info(self):
return 42
Run Code Online (Sandbox Code Playgroud)
事情停止了.该super()
基类的构造函数调用突然来电Logger.__init__()
,并且BLogged
不能做任何事情.实际上没有办法使这项工作,除了自己删除super()
调用B
.
[ 另一个编辑:我似乎没有提出我的观点,从这里和其他答案的所有评论来判断.以下是如何使用以下代码super()
:
class A(object):
def __init__(self, i, **kwargs):
super(A, self).__init__(**kwargs)
self.i = i
def run(self, value):
return self.i * value
class B(A):
def __init__(self, j, **kwargs):
super(B, self).__init__(**kwargs)
self.j = j
def run(self, value):
return super(B, self).run(value) + self.j
class Logger(object):
def __init__(self, name, **kwargs):
super(Logger,self).__init__(**kwargs)
self.name = name
def run_logged(self, value):
print "Running", self.name, "with info", self.info()
return self.run(value)
class BLogged(B, Logger):
def __init__(self, **kwargs):
super(BLogged, self).__init__(name="B", **kwargs)
def info(self):
return 42
b = BLogged(i=3, j=4)
Run Code Online (Sandbox Code Playgroud)
将此与显式超类调用的使用进行比较.您决定您喜欢哪个版本.]
这个和类似的故事是我认为不super()
应该被认为是调用基类方法的标准方法的原因.这并不意味着super()
被打破.
Len*_*bro 31
super()
在Python 2或Python 3中没有被破坏.
让我们考虑博客文章中的论点:
好的,你可能同意或不同意,这是非常主观的.应该怎么称呼呢?super()
是直接调用超类的替代品,所以这个名字对我来说似乎很好.它不会直接调用超类,因为如果这就是它所做的全部,那将毫无意义,因为无论如何你都可以这样做.不可否认,这可能并不明显,但您需要的super()
情况通常并不明显.如果你需要它,你正在做一些非常多毛的多重继承.这不会很明显.(或者你正在做一个简单的mixin,在这种情况下,即使你没有阅读文档,它也会非常明显并且表现得如你所愿).
如果你可以直接调用超类,那可能就是你最终会做的事情.这是一种简单直观的方法.super()
只有在不起作用时才会发挥作用.
是的,因为它旨在解决这样做的问题.您可以直接调用超类,只有当您确切知道该类是什么时,才能直接调用它.例如,你没有使用mixins,或者你的类层次结构如此混乱以至于你实际上正在合并两个分支(这是所有使用示例中的典型示例super()
).
因此,只要类层次结构中的每个类都有一个定义良好的位置,就可以直接调用超类.如果你不这样做,那么它就不起作用了,在这种情况下你必须使用它super()
.这super()
就是它根据MRO确定"下一个超类"的含义,而不必明确指定它,因为你不能总是这样做,因为你并不总是知道它是什么,例如当使用mixins.
呃.好?
super()
不会打电话给你的超类.是的,你这么说.
super()
和指挥呼叫.是的,你也说过.
因此,有两个反对它的论点:1.名称不好.你必须始终如一地使用它.
这并不意味着它被"破坏"或者应该"避免".
你似乎暗示你的帖子
def some_func(self, *args, **kwargs):
self.__class__.some_func(self, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
不是无限递归.它是,超级更正确.
此外,是的,您需要传递所有参数super()
.这有点像抱怨,max()
除非你传递它想要检查的所有数字,否则它不会像预期的那样工作.
但是,在3.x中,需要的参数较少:您可以super().foo(*args, **kwargs)
代替super(ThisClass, self).foo(*args, **kwargs)
.
无论如何,我不确定应该避免超级的任何情况.当MI涉及时,它的行为只是"奇怪",当涉及MI时,super()
基本上是你唯一希望得到正确的解决方案.在单一继承中,它只是略显冗长SuperClass.foo(self, *args, **kwargs)
,并没有什么不同.
我认为我同意Sven认为这种MI是值得避免的,但我不同意这super
是值得避免的.如果你的课程应该被继承,那么你的班级super
用户希望让MI工作,如果他们以这种方式很奇怪,那么它会使你的课程更有用.
归档时间: |
|
查看次数: |
52649 次 |
最近记录: |