Earlier quoted context omitted.
Dicts are UNORDERED associative containers. If youre depending your app on implementation defined behavior, that's on your developpers shoulders. Stuff like that shouldn't pass code review
Not for much longer, as of 3.7 the ordering is a language feature: https://mail.python.org/pipermail/python-dev/2017-December/1... It's mad that it ever wasn't this way. Mapping-with-ordered-keys is such a useful and pervasive data structure (all database query result rows, for one) that an ordered dictionary should be a fundamental part of a language. It has been so much more pleasant to write python since ordering…
Migrating to Python 3 with pleasure
31–40 of 181 posts
Re: Migrating to Python 3 with pleasure
#32In particular, being able to create an updated copy of a dict with a single expression is pretty cool:
return {**old, 'foo': 'bar'}
# Old way
new = old.copy
new['foo'] = ['bar']
return newRe: Migrating to Python 3 with pleasure
#33I've been toying around with Python 3 and using it for most of my personal/hack projects, but I somehow missed the unpacking improvements: https://www.python.org/dev/peps/pep-0448/ In particular, being able to create an updated copy of a dict with a single expression is pretty cool: return {**old, 'foo': 'bar'} # Old way new = old.copy new['foo'] = ['bar'] return new
[*a, *b, *c]Re: Migrating to Python 3 with pleasure
#34I've been toying around with Python 3 and using it for most of my personal/hack projects, but I somehow missed the unpacking improvements: https://www.python.org/dev/peps/pep-0448/ In particular, being able to create an updated copy of a dict with a single expression is pretty cool: return {**old, 'foo': 'bar'} # Old way new = old.copy new['foo'] = ['bar'] return new
In [1]: x = {1:2, 3:4}
In [2]: %timeit x[3] = 5
48.6 ns ± 1.18 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [3]: %timeit y = x.copy(); y[3] = 5
189 ns ± 3.23 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [4]: %timeit {**x, 3: 5}
182 ns ± 3.3 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
Edit: It also seems to be pretty constant time if you're just merging: In [16]: %timeit {**x, **y, **z}
180 ns ± 1.29 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [17]: %timeit {**x, **y, **z, 3: 5}
278 ns ± 18.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [19]: dis.dis(lambda: {**x, **y, **z, 3: 5})
0 LOAD_GLOBAL 0 (x)
2 LOAD_GLOBAL 1 (y)
4 LOAD_GLOBAL 2 (z)
6 LOAD_CONST 1 (3)
8 LOAD_CONST 2 (5)
10 BUILD_MAP 1
12 BUILD_MAP_UNPACK 4
14 RETURN_VALUE
In [20]: dis.dis(lambda: {**x, **y, **z})
0 LOAD_GLOBAL 0 (x)
2 LOAD_GLOBAL 1 (y)
4 LOAD_GLOBAL 2 (z)
6 BUILD_MAP_UNPACK 3
8 RETURN_VALUERe: Migrating to Python 3 with pleasure
#35I realized, just today, that the secrets module is new to 3.6 after trying to pip install it. This being provided directly by the language is a game changer, IMHO.
Re: Migrating to Python 3 with pleasure
#36Earlier quoted context omitted.
Not for much longer, as of 3.7 the ordering is a language feature: https://mail.python.org/pipermail/python-dev/2017-December/1... It's mad that it ever wasn't this way. Mapping-with-ordered-keys is such a useful and pervasive data structure (all database query result rows, for one) that an ordered dictionary should be a fundamental part of a language. It has been so much more pleasant to write python since ordering…
>>(all database query result rows, for one) What? No. SQL does not return results in any consistent ordering unless specifically instructed to.
Re: Migrating to Python 3 with pleasure
#37Earlier quoted context omitted.
> test_path = datasets_root / dataset / 'test' > Previously it was always tempting to use string concatenation (concise, but obviously bad), now with pathlib the code is safe, concise, and readable. This is the kind of feature that I'm wary to use even in scripts: questionable benefit, and probably too clever.
I don't have a machine available right now, but I wonder what happens if two adjacent path elements are integers? Does it perform division instead of path/string concatenation?
>>> from pathlib import Path
>>> p=Path(1)
Traceback (most recent call last):
File "", line 1, in
File "/usr/lib/python3.6/pathlib.py", line 979, in __new__
self = cls._from_parts(args, init=False)
File "/usr/lib/python3.6/pathlib.py", line 654, in _from_parts
drv, root, parts = self._parse_args(args)
File "/usr/lib/python3.6/pathlib.py", line 638, in _parse_args
a = os.fspath(a)
TypeError: expected str, bytes or os.PathLike object, not int
>>>
So what happens if the paths are numbers? They are treated like any other characters.Re: Migrating to Python 3 with pleasure
#38I've moved to python 3 over the past couple of months, after resisting for the better part of a decade. I like it. One surprising thing I learned from this document is that dicts now iterate in assignment order, not hash order. That's going to break some code for people.
Personally, I'm worried people will come to rely on the new behaviour in code instead. As core developers have repeatedly said, dict order is still an implementation detail, it should not be relied on as it is not officially part of the language. Other implementations (except pypy) will probably not have this behaviour.
Yet, I feel like this will fall on deaf ears and become a de-facto part of the language. Blogs will state it as a new feature, Python books will teach it and new coders will rely on it, forever locking the dict internals in place for all python interpreters.
(If you need to rely on ordering, use an OrderedDict instead.)
Re: Migrating to Python 3 with pleasure
#39I've been toying around with Python 3 and using it for most of my personal/hack projects, but I somehow missed the unpacking improvements: https://www.python.org/dev/peps/pep-0448/ In particular, being able to create an updated copy of a dict with a single expression is pretty cool: return {**old, 'foo': 'bar'} # Old way new = old.copy new['foo'] = ['bar'] return new
return {**old, 'foo': 'bar'}
# Old way
return dict(old, foo='bar')
Not much difference if you ask me.Re: Migrating to Python 3 with pleasure
#40I've been toying around with Python 3 and using it for most of my personal/hack projects, but I somehow missed the unpacking improvements: https://www.python.org/dev/peps/pep-0448/ In particular, being able to create an updated copy of a dict with a single expression is pretty cool: return {**old, 'foo': 'bar'} # Old way new = old.copy new['foo'] = ['bar'] return new
return {**old, 'foo': 'bar'} # Old way return dict(old, foo='bar') Not much difference if you ask me.