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.turner@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 <abarnert@yahoo.com> wrote:
On Nov 30, 2019, at 20:21, Wes Turner <wes.turner@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-leave@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/OA7NQR... Code of Conduct: http://python.org/psf/codeofconduct/