Issue32854
Created on 2018-02-15 18:10 by John Crawford, last changed 2022-04-11 14:58 by admin. This issue is now closed.
| Messages (7) | |||
|---|---|---|---|
| msg312218 - (view) | Author: John Crawford (John Crawford) | Date: 2018-02-15 18:10 | |
At present, `collections.namedtuple` does not support `**` map unpacking despite being a mapping style data structure. For example:
>>> from collections import namedtuple
>>> A = namedtuple("A", "a b c")
>>> a = A(10, 20, 30)
>>> def t(*args, **kwargs):
... print(f'args={args!r}, kwargs={kwargs!r}')
...
>>> t(*a)
args=(10, 20, 30), kwargs={}
>>> t(**a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: t() argument after ** must be a mapping, not A
>>>
No doubt, the lack of current support is due to namespace conflicts that result from trying to provide a `keys` method amidst also supporting attribute-style access to the `namedtuple` class. As we can see, providing a `keys` attribute in the `namedtuple` produces an interesting result:
>>> Record = namedtuple("Record", "title keys description")
>>> t(**Record(1, 2, 3))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: attribute of type 'int' is not callable
>>>
To me, this calls out a design flaw in the `**` unpacking operator where it depends on a method that uses a non-system naming convention. It would make far more sense for the `**` operator to utilize a `__keys__` method rather than the current `keys` method. After all, the `__<methodname>__` naming convention was introduced to avoid namespace conflict problems like this one.
|
|||
| msg312219 - (view) | Author: Raymond Hettinger (rhettinger) * ![]() |
Date: 2018-02-15 18:52 | |
The intended way to support **unpacking is the _asdict() method:
t(**a._asdict())
It doesn't really make sense to add direct support for **unpacking because named tuples are sequences and not mappings. To support **unpacking, we would have to add a keys() method and modify __getitem__() to handle both integer indexing and string key lookup. Once we have **a and a[k] and a.keys(), people would also want a.values() a.items() etc. The world gets murky when both sequence and mapping behaviors become commingled.
|
|||
| msg312220 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * ![]() |
Date: 2018-02-15 19:26 | |
Concur with Raymond. |
|||
| msg312252 - (view) | Author: Jay Crotts (jcrotts) * | Date: 2018-02-16 20:41 | |
Would it be worth adding an example of unpacking such as, t(**a._asdict()), or something similar to the documentation ? |
|||
| msg312276 - (view) | Author: Raymond Hettinger (rhettinger) * ![]() |
Date: 2018-02-17 08:13 | |
> Would it be worth adding an example of unpacking such as, > t(**a._asdict()), or something similar to the documentation ? There are a myriad of uses for dictionaries and the namedtuple docs don't seem like to right place to cover them (**unpacking, str.format_map, str.__mod__, etc). Even the dict and OrderedDict docs don't cover these. Also, the use of somefunc(**nt._asdict()) isn't a common pattern. A requirement for **unpacking tends to nudge design choices towards an actual mapping rather than a tuple or tuple subclass for the underlying data store. That is likely why this hasn't come-up before. |
|||
| msg312277 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * ![]() |
Date: 2018-02-17 08:42 | |
I wandering if it is worth to add a general function that takes an object and a sequence of keys and return a mapping proxy that maps attribute names to values. |
|||
| msg312359 - (view) | Author: Jay Crotts (jcrotts) * | Date: 2018-02-19 18:33 | |
Thanks Raymond, I wasn't sure if it was a common pattern or not, that makes sense. |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022-04-11 14:58:57 | admin | set | github: 77035 |
| 2018-03-04 21:50:45 | serhiy.storchaka | set | status: open -> closed resolution: rejected stage: resolved |
| 2018-02-19 18:33:31 | jcrotts | set | messages: + msg312359 |
| 2018-02-17 08:42:37 | serhiy.storchaka | set | messages: + msg312277 |
| 2018-02-17 08:13:55 | rhettinger | set | messages: + msg312276 |
| 2018-02-16 20:41:34 | jcrotts | set | nosy:
+ jcrotts messages: + msg312252 |
| 2018-02-15 19:26:25 | serhiy.storchaka | set | nosy:
+ serhiy.storchaka messages: + msg312220 |
| 2018-02-15 18:52:50 | rhettinger | set | nosy:
+ rhettinger messages: + msg312219 |
| 2018-02-15 18:10:32 | John Crawford | create | |
