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.