>>> for item in data.items(): item[0], item[1]
874 µs ± 21.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> for key, value in data.items(): key, value
524 µs ± 4.26 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> for item in items_tuple(data): item.key, item.value
5.82 ms ± 117 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Thanks for sharing the results, in particular the amount of difference
between "for item in data.items(): item[0], item[1]" and "for key in
data.items(): key, value" is a bit surprising to me. I'd have assumed
they'd be a bit closer in performance. I expected the named tuple to be
significantly slower than the other two, but not quite by that much. Good
to know.

I'm -1 on the proposal overall. It's not a bad idea, but in practice it
would likely be too much of a detriment to performance and backwards
compatibility to "dict.items()". I wouldn't be opposed to considering a
different method though, such as "dict.named_items()" or something similar
that allowed usage of "item.key" and "item.value".

On Sun, Dec 1, 2019 at 7:56 AM Wes Turner <wes.tur...@gmail.com> wrote:

> My mistake, I skimmed and assumed that the question was asking for this:
>
> from collections import namedtuple
> data = {'1': 1, 'two-2': 2}
> x = namedtuple('x', data.keys())
> # ValueError: Type names and field names must be valid identifiers: '1'
>
> # But now understand that the request was for this:
>
> from collections import namedtuple
> Item = namedtuple('Item', ['key', 'value'])
>
> def items_tuple(self):
>     for key, value in self.items():
>         yield Item(key, value)
>
> # So that this test would pass:
>
> def test_items():
>     data = {'1': 1, 'two-2': 2}
>     for item in data.items():
>         assert hasattr('key', item)
>         assert hasattr('value', item)
>         key, value = item
>         assert item.key == key
>         assert item.value == value
>
> # FWIW, here are rough timings:
>
> data = dict.fromkeys(range(10000))
>
> def timeit(code):
>     print(f">>> {code}")
>     get_ipython().run_line_magic('timeit', code)
>
> timeit('for item in data.items(): item[0], item[1]')
> timeit('for key, value in data.items(): key, value')
> timeit('for item in items_tuple(data): item.key, item.value')
>
> >>> for item in data.items(): item[0], item[1]
> 874 µs ± 21.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
> >>> for key, value in data.items(): key, value
> 524 µs ± 4.26 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
> >>> for item in items_tuple(data): item.key, item.value
> 5.82 ms ± 117 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>
> On Sun, Dec 1, 2019 at 1:24 AM Andrew Barnert <abarn...@yahoo.com> wrote:
> >
> > On Nov 30, 2019, at 20:21, Wes Turner <wes.tur...@gmail.com> wrote:
> > >
> > > What about keys that contain invalid characters for attribute names?
> >
> > What about them?
> >
> > > items = {'1': 1, 'two-3': 4,}
> > > x = object()
> > > x.__dict__.update(items) # dangerous
> > > x = AttrDict(**items)
> > > x.1     # error
> > > x.two-3 # error
> >
> > The message you quoted was about how in Python 2 (but not 3) you could
> destructure parameters:
> >
> >     sorted({1:300, 2:4}.items(), key=lambda (key, value): value)
> >
> > The wider discussion is about how if items() were a view of namedtuples
> instead of just sequences you could do something even better:
> >
> >     sorted({1:300, 2:4}.items(), key=lambda it: it.value)
> >
> > What does either of those have to do with using a dict whose keys are
> not identifiers as an attribute dictionary for an object? Neither restoring
> Python 2’s parameter destructuring nor making items namedtuples would in
> any way affect any of the code you wrote.
> >
> >
> _______________________________________________
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/OA7NQRF4VTFG2DJVNJAAJ7YIQNB3IVVR/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/76Y6PK74TLQFWNLE4CO3WAGBUPMQ62WL/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to