Message384490
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. |
|
Date |
User |
Action |
Args |
2021-01-06 11:25:59 | conqp | set | recipients:
+ conqp, zzzeek, xtreak |
2021-01-06 11:25:59 | conqp | set | messageid: <1609932359.6.0.384727611958.issue41629@roundup.psfhosted.org> |
2021-01-06 11:25:59 | conqp | link | issue41629 messages |
2021-01-06 11:25:59 | conqp | create | |
|