New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
super behaviour and abstract base classes (either implementation or documentation/error message is wrong) #64702
Comments
When using an abstract base class, super(type, obj) throws a TypeError stating "obj must be an instance (...) of type", even though isinstance(obj, type) returns True. I'm not sure what is supposed to happen here, but either the error message and the documentation for super would need to be reformulated, or there is an issue with the implementation, or I am misunderstanding something. Python 3.3.3 (default, Dec 12 2013, 11:13:02)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numbers
>>> super(numbers.Number, 0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> isinstance(0, numbers.Number)
True |
Given super(cls, obj), cls needs to be somewhere in type(obj).__mro__. Thus the implementation checks PyType_IsSubtype instead of the more generic PyObject_IsSubclass. In this case int's MRO is unrelated to numbers.Number: >>> print(*int.__mro__, sep='\n')
<class 'int'>
<class 'object'> It gets registered as a subclass via numbers.Integral.register(int). >>> print(*numbers.Integral._abc_registry)
<class 'int'> issubclass calls PyObject_IsSubclass, which uses the __subclasscheck__ API. In this case ABCMeta.__subclasscheck__ recursively checks the registry and caches the result to speed up future checks. >>> numbers.Number.__subclasscheck__(int)
True
>>> print(*numbers.Number._abc_cache)
<class 'int'> |
I am proposing some documentation changes in bpo-23674 which would address this. |
The docs still need to clarified that isinstance(obj, type) is a necessary but not sufficient condition for success. It would also be helpful if the error message were less confusing in the case of registered subclasses such as numbers.Number. |
This is a bit out of date. The isinstance() docs now specify that the predicate tests for direct, indirect, and virtual inheritance. Likewise, the super() docs already specify that only the __mro__ is searched. So those docs are already precise. Am thinking of adding a FAQ entry about when direct inheritance is required and include the OP's example. FWIW, this isn't really about super(). It affects any attribute lookup or any other property of inheritance. A true result from instance() doesn't imply that actual inheritance has occurred. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: