Eric V. Smith <e...@trueblade.com> added the comment:

The question here is: what should asdict() return if the dataclass contains a 
namedtuple? What the code is trying to do (but currently failing!) is to return 
another namedtuple, but with the values returned by recursively calling in to 
asdict() (or rather, its helper function) for each field in the namedtuple.

I think this is the correct behavior. Specifically, I do not want to call the 
namedtuple's _asdict() method. There are two problems with _asdict():

1. It doesn't recurse in to the fields, like asdict() normally does with a 
dict, list, or tuple.

2. It returns a dict! This is a problem because if a dataclass field contains a 
dict which has a key which is a namedtuple, then asdict() would fail.

Here's an example of #2 above, if asdict() on a namedtuple field returns a dict:

@dataclass
class C:
    f: 'Any'

T = namedtuple('T', 'a')

c = C({T('an a'): 0})
print('c:', c)
print(asdict(c))   # <- error here

prints:

c: C(f={T(a='an a'): 0})
Traceback (most recent call last):
...
  File "/home/eric/python/lib/dataclasses.py", line 1019, in asdict
    return _asdict_inner(obj, dict_factory)
  File "/home/eric/python/lib/dataclasses.py", line 1026, in _asdict_inner
    value = _asdict_inner(getattr(obj, f.name), dict_factory)
  File "/home/eric/python/lib/dataclasses.py", line 1059, in _asdict_inner
    for k, v in obj.items())
TypeError: unhashable type: 'collections.OrderedDict'

So, although it's unfortunate, I think the only reasonable thing to do in this 
case is to have asdict() on a namedtuple return another namedtuple. Here's how 
that looks using the above code:

c: C(f={T(a='an a'): 0})
{'f': {T(a='an a'): 0}}

Admittedly, this can't be used with json.dumps() (you get "TypeError: keys must 
be str, int, float, bool or None, not T"), but I think it's the best we can do. 
It's consistent with any other class derived from tuple or list: asdict() will 
convert it to a copy of the class, recursing into each item that's in the tuple 
or list.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue34363>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to