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 self argument
foo
bar
>>> B.f(B) # non-instance self 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'
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 self argument
foo
bar
>>> B.f(B) # non-instance self argument
foo
bar
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>
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 self
argument that is an instance of the class (like the first B.f
implementation which always calls super().f
as a bound method, i.e. super().f()
), or should he also handle the situation where the self
argument is not an instance of the class* (like the second B.f
implementation which calls super().f
as a bound method, i.e. super().f()
, or as a function, i.e. super().f(self)
)?
* This is possible since Python 3.0 to allow advanced usages, as Guido van Rossum explained:
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.