Closed as not planned
Description
Bug report
Hi everyone,
Consider the following example
class A: pass
a = A()
a.attr = 1
print(type(A.__dict__['__dict__']))
print('attr' in A.__dict__['__dict__'].__get__(a))
del a.__dict__ # getset_descriptor works
print(a.__dict__)
While everything is clear here, consider another one:
class B:
__dict__ = None # or whatever
b = B()
b.attr = 1
print(type(B.__dict__['__dict__'])) # this is not getset_descriptor anymore
print('attr' in dir(b))
print(hasattr(b, 'attr'))
print(b.attr) # available, but stored in 'original/hidden C-level' __dict__
b.__dict__ = "abracadabra" # now this works without getset_descriptor...
Of course, we got the __dict__
which is not usable as normal one. For example, when we try to use it in interactive mode,
it tries to autocomplete based on this defined __dict__
:
>>> class C:
... __dict__ = {'myfun': lambda self: ...}
...
>>> c = C()
>>> c.myfun() # autocompleted with TAB here
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute 'myfun'
What is the purpose to allow defining __dict__
in a such way in class body?
Perhaps it would be better to raise some error on a class creation.
Environment
- CPython versions tested on: 3.9.7 (python3-3.9.7-1.fc33.x86_64)
- Operating system and architecture: Fedora 33 x86_64