You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
super behaviour and abstract base classes (either implementation or documentation/error message is wrong) #64702
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:
assignee='https://github.com/rhettinger'closed_at=<Date2021-04-05.20:12:39.078>created_at=<Date2014-02-03.15:36:42.585>labels= ['interpreter-core', 'type-bug', '3.8', '3.9', '3.10']
title='super behaviour and abstract base classes (either implementation or documentation/error message is wrong)'updated_at=<Date2021-04-05.20:12:39.077>user='https://github.com/gerritholl'
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
changed the title [-]super behavioru and abstract base classes (either implementation or documentation/error message is wrong)[/-][+]super behaviour and abstract base classes (either implementation or documentation/error message is wrong)[/+]on Feb 12, 2015
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:
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.
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.
New changeset 028d528 by Miss Islington (bot) in branch '3.9': bpo-20503: Show how isinstance() works with ABC registered classes. (GH-25175) (GH-25202) 028d528
Activity
gerritholl commentedon Feb 3, 2014
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.
[-]super behavioru and abstract base classes (either implementation or documentation/error message is wrong)[/-][+]super behaviour and abstract base classes (either implementation or documentation/error message is wrong)[/+]eryksun commentedon Feb 12, 2015
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'>vadmium commentedon Dec 2, 2015
I am proposing some documentation changes in bpo-23674 which would address this.
eryksun commentedon Feb 26, 2021
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.
rhettinger commentedon Feb 28, 2021
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.
rhettinger commentedon Apr 5, 2021
New changeset 7bc25ec by Raymond Hettinger in branch 'master':
bpo-20503: Show how isinstance() works with ABC registered classes. (GH-25175)
7bc25ec
rhettinger commentedon Apr 5, 2021
New changeset 028d528 by Miss Islington (bot) in branch '3.9':
bpo-20503: Show how isinstance() works with ABC registered classes. (GH-25175) (GH-25202)
028d528