用super()检索的可调用对象应如何调用? [英] How should callables retrieved with super() be called?
问题描述
我注意到,通过此 B.f
实现,调用 B.f(B)
会引发 TypeError
:
I noticed that with this B.f
implementation, the call B.f(B)
raises a TypeError
:
>>> class A:
... def f(self): print('foo')
...
>>> class B(A):
... def f(self):
... super().f()
... print('bar')
...
>>> B.f(B()) # instance first argument
foo
bar
>>> B.f(B) # non-instance first argument
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in f
TypeError: f() missing 1 required positional argument: 'self'
但是通过这种 B.f
实现,调用 B.f(B)
可以起作用:
But with this B.f
implementation, the call B.f(B)
works:
>>> class A:
... def f(self): print('foo')
...
>>> class B(A):
... def f(self):
... if isinstance(self, B): super().f() # bound method call
... else: super().f(self) # function call
... print('bar')
...
>>> B.f(B()) # instance first argument
foo
bar
>>> B.f(B) # non-instance first argument
foo
bar
这是因为 super().f
(即 super(B,self).f
)检索绑定方法 types.MethodType(Af,self)
,当 self
是 B
的实例,并检索 function Af
否则:
This is because super().f
(i.e. super(B, self).f
) retrieves the bound method types.MethodType(A.f, self)
when self
is an instance of B
, and retrieves the function A.f
otherwise:
>>> super(B, B()).f
<bound method A.f of <__main__.B object at 0x10e6bda90>>
>>> super(B, B).f
<function A.f at 0x10e7d6790>
所以我想知道上面的两个 B.f
实现中哪一个是惯用的.换句话说,类设计者应该假设将始终使用作为类实例的第一个参数来调用类的功能(例如,总是调用 super的第一个
作为绑定方法),还是他也应该处理第一个参数不是该类*实例的情况(例如第二个 Bf
实现)().f Bf
实现,它调用 super().f
作为绑定方法或作为函数)?
So I wonder which of the two B.f
implementations above is idiomatic. In other words, should a class designer assume that the functions of the class will always be called with a first argument that is an instance of the class (like the first B.f
implementation which always calls super().f
as a bound method), or should he also handle the situation where the first argument is not an instance of the class* (like the second B.f
implementation which calls super().f
as a bound method or as a function)?
*从Python 3.0开始,这可能允许高级用法,例如Guido van Rossum 解释:
* This is possible since Python 3.0 to allow advanced usages, as Guido van Rossum explained:
在Python 3000中,未绑定方法的概念已被删除,表达式"A.spam"已被删除.返回一个普通的函数对象.事实证明,第一个参数必须是A的实例的限制很少有助于诊断问题,并且常常是高级用法的障碍-有些人称其为鸭式自我".似乎是个合适的名字.
In Python 3000, the concept of unbound methods has been removed, and the expression "A.spam" returns a plain function object. It turned out that the restriction that the first argument had to be an instance of A was rarely helpful in diagnosing problems, and frequently an obstacle to advanced usages --- some have called it "duck typing self" which seems an appropriate name.
推荐答案
我刚刚通过此 Ag
实现认识到,该问题并非特定于使用 super()
:
I have just realised with this A.g
implementation that the issue is not specific to using super()
:
>>> class A:
... def f(self): print('foo')
... def g(self):
... self.f()
... print('bar')
...
>>> A.g(A())
foo
bar
>>> A.g(A)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in g
TypeError: f() missing 1 required positional argument: 'self'
我们通常不编写此 A.g
实现:
We typically don’t write this A.g
implementation:
>>> class A:
... def f(self): print('foo')
... def g(self):
... if isinstance(self, A): self.f() # bound method call
... else: self.f(self) # function call
... print('bar')
...
>>> A.g(A())
foo
bar
>>> A.g(A)
foo
bar
但是我们应该吗?我想知道Guido van Rossum所指的这些非实例优先论证的先进用法"是什么.
But should we? I wonder what are these ‘advanced usages’ of non-instance first arguments that Guido van Rossum is referring to.
这篇关于用super()检索的可调用对象应如何调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!