[issue41629] __class__ not set defining 'X' as <class '__main__.X'>
Richard Neumann
report at bugs.python.org
Wed Jan 6 06:25:59 EST 2021
Richard Neumann <mail at richard-neumann.de> added the comment:
I just stumbled across this issue trying to resolve this: https://bugs.python.org/issue42765?
While this fails:
from typing import NamedTuple
class Spamm(NamedTuple):
foo: int
bar: str
def __getitem__(self, index_or_key):
"""Returns the respective item."""
if isinstance(index_or_key, str):
try:
return getattr(self, index_or_key)
except AttributeError:
raise IndexError(index_or_key) from None
return super().__getitem__(index_or_key)
def keys(self):
return self._fields
def main():
spamm = Spamm(12, 'hello')
print(dir(spamm))
print(spamm._fields)
d = dict(spamm)
print(d)
if __name__ == '__main__':
main()
with
Traceback (most recent call last):
File "/home/neumann/test.py", line 4, in <module>
class Spamm(NamedTuple):
RuntimeError: __class__ not set defining 'Spamm' as <class '__main__.Spamm'>. Was __classcell__ propagated to type.__new__?
The following works:
from typing import NamedTuple
def _getitem(instance, index_or_key):
"""Returns the respective item."""
if isinstance(index_or_key, str):
try:
return getattr(instance, index_or_key)
except AttributeError:
raise IndexError(index_or_key) from None
return super().__getitem__(index_or_key)
def dicttuple(cls: tuple):
"""Extends a tuple class with methods for the dict constructor."""
cls.keys = lambda self: self._fields
cls.__getitem__ = _getitem
return cls
@dicttuple
class Spamm(NamedTuple):
foo: int
bar: str
def main():
spamm = Spamm(12, 'hello')
print(dir(spamm))
print(spamm._fields)
d = dict(spamm)
print(d)
if __name__ == '__main__':
main()
And produces:
['__add__', '__annotations__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__mul__', '__ne__', '__new__', '__orig_bases__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '_asdict', '_field_defaults', '_fields', '_make', '_replace', 'bar', 'count', 'foo', 'index', 'keys']
('foo', 'bar')
{'foo': 12, 'bar': 'hello'}
I am a bit baffled, why it works when the method is injected via a decorator.
----------
nosy: +conqp
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue41629>
_______________________________________
More information about the Python-bugs-list
mailing list