这个Python 2示例 :
class LoggingDict(dict): # Simple example of extending a builtin class def __setitem__(self, key, value): logging.info('Setting %r to %r' % (key, value)) super(LoggingDict, self).__setitem__(key, value)这个Python 3的例子 :
class LoggingDict(dict): # Simple example of extending a builtin class def __setitem__(self, key, value): logging.info('Setting %r to %r' % (key, value)) super().__setitem__(key, value)说明了Python 2的super需要显式类和self参数的事实(但Python 3没有)。 这是为什么? 这似乎是一个恼人的限制。
This Python 2 example:
class LoggingDict(dict): # Simple example of extending a builtin class def __setitem__(self, key, value): logging.info('Setting %r to %r' % (key, value)) super(LoggingDict, self).__setitem__(key, value)and this Python 3 example:
class LoggingDict(dict): # Simple example of extending a builtin class def __setitem__(self, key, value): logging.info('Setting %r to %r' % (key, value)) super().__setitem__(key, value)illustrate the fact that Python 2's super requires explicit class and self arguments (but Python 3's doesnt). Why is that? It seems like an irritating limitation.
最满意答案
AKS评论中的链接提供了答案:
让我们说在Python 2的例子中,我认为“我不喜欢那个显式的类引用。如果我更改类的名称或移动此代码并忘记更新它会怎么样?”。 让我们说,我想,我会用self.__class__替换显式类名,并写道:
class LoggingDict(dict): # Simple example of extending a builtin class def __setitem__(self, key, value): logging.info('Setting %r to %r' % (key, value)) super(self.__class__, self).__setitem__(key, value)现在我创建了一个名为LoggingDict SpecialisedLoggingDict的子类(它不会覆盖__setitem__ ),实例化它并在其上调用__setitem__ 。
现在self指的是SpecialisedLoggingDict一个实例,所以super返回LoggingDict ,然后我们直接回到LoggingDict.__setitem__ ,进入无限递归。
关键点在于Python 2中的方法并不真正知道它所定义的类,它只知道调用它的实例的类 。 Python 3 执行编译时“魔术” ,向函数添加__class__单元格,以便在没有显式类引用的情况下使用super() 。
The link in AKS' comment provides the answer here:
Lets say in the Python 2 example I thought "I don't like that explicit class reference. What if I change the name of the class or move this code and forget to update it?". Lets say I thought, a-ha, I'll replace the explicit class name with self.__class__ and wrote:
class LoggingDict(dict): # Simple example of extending a builtin class def __setitem__(self, key, value): logging.info('Setting %r to %r' % (key, value)) super(self.__class__, self).__setitem__(key, value)Now I create a subclass called SpecialisedLoggingDict of LoggingDict (which doesn't override __setitem__), instantiate it and call __setitem__ on it.
Now self refers to an instance of SpecialisedLoggingDict, so the super returns LoggingDict, and we go straight back into LoggingDict.__setitem__, entering infinite recursion.
The essential point is that in Python 2 a method doesn't really know which class it was defined in, it only knows the class of the instance on which it's being called. Python 3 does compile-time "magic", adding a __class__ cell to functions so that super() can be used without the explicit class reference.
更多推荐
发布评论