Message408192
The plot thickens.
I was wrong to say that type() always and only looks at the "real" underlying type of the instance. type() does look at __class__ as well. But only sometimes.
>>> class A:
... __class__ = int
...
>>> type(A())
<class '__main__.A'>
>>> a = A()
>>> a.__class__ = int
>>> type(a)
<class '__main__.A'>
So from A, we might think that type() ignores __class__
>>> class B:
... pass
...
>>> type(B()) # no __class__ to inspect
<class '__main__.B'>
>>> b = B()
>>> b.__class__ = int
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __class__ assignment only supported for mutable types or ModuleType subclasses
How very odd. But okay, let's try something else:
>>> b.__class__ = A # lie that this is an A not a B
>>> type(b)
<class '__main__.A'>
So now type() *does* inspect __class__, and believes it.
If we generate the __class__ attribute dynamically with __getattr__, the method doesn't even get called. But if we use __getattribute__:
>>> class C:
... def __getattribute__(self, name):
... print('C getattribute:', name)
... if name == '__class__':
... return int
... raise AttributeError
...
>>> C().__class__
C getattribute: __class__
<class 'int'>
>>> type(C())
<class '__main__.C'>
type() ignores the dynamically generated __class__. But isinstance does not:
>>> isinstance(C(), int)
C getattribute: __class__
True
The same applies if we use property:
>>> class D:
... @property
... def __class__(self):
... return int
...
>>> type(D())
<class '__main__.D'>
>>> isinstance(D(), int)
True
So the rules appear to be:
- you can set __class__, but only sometimes;
- type() will believe __class__, but only sometimes;
- you can generate __class__ dynamically, but not with __getattr__;
- isinstance() will believe __class__ (always?);
- and there is no indication of how much of this is deliberate language feature and how much is an accident of implementation. |
|
Date |
User |
Action |
Args |
2021-12-10 11:41:23 | steven.daprano | set | recipients:
+ steven.daprano, rhettinger, paul.moore, r.david.murray, ethan.furman, bup, Gabriele Tornetta |
2021-12-10 11:41:23 | steven.daprano | set | messageid: <1639136483.47.0.941159479942.issue32683@roundup.psfhosted.org> |
2021-12-10 11:41:23 | steven.daprano | link | issue32683 messages |
2021-12-10 11:41:23 | steven.daprano | create | |
|