[Django] #28909: Use unpacking generalizations added in Python 3.5

19 views
Skip to first unread message

Django

unread,
Dec 8, 2017, 11:21:36 AM12/8/17
to django-...@googlegroups.com
#28909: Use unpacking generalizations added in Python 3.5
-------------------------------------+-------------------------------------
Reporter: Nick Pope | Owner: Nick Pope
Type: | Status: assigned
Cleanup/optimization |
Component: | Version: master
Uncategorized |
Severity: Normal | Keywords: unpacking
Triage Stage: | Has patch: 1
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
Now that master is Python 3.5+ we can look to using unpacking
generalizations for dict, list, set and tuple.

https://docs.python.org/3.5/whatsnew/3.5.html#whatsnew-pep-448

One benefit to this is that slow function/method calls can avoided and
specific operations for unpacking are used instead:

{{{#!console
$ python -c "import dis; dis.dis(\"d0 = {'a': 1}; d1 = {'b': 2}; x =
{**d0, **d1}\")"
1 0 LOAD_CONST 0 ('a')
2 LOAD_CONST 1 (1)
4 BUILD_MAP 1
6 STORE_NAME 0 (d0)
8 LOAD_CONST 2 ('b')
10 LOAD_CONST 3 (2)
12 BUILD_MAP 1
14 STORE_NAME 1 (d1)
16 LOAD_NAME 0 (d0)
18 LOAD_NAME 1 (d1)
20 BUILD_MAP_UNPACK 2
22 STORE_NAME 2 (x)
24 LOAD_CONST 4 (None)
26 RETURN_VALUE

$ python -c "import dis; dis.dis(\"d0 = {'a': 1}; d1 = {'b': 2}; x =
dict(d0, **d1)\")"
1 0 LOAD_CONST 0 ('a')
2 LOAD_CONST 1 (1)
4 BUILD_MAP 1
6 STORE_NAME 0 (d0)
8 LOAD_CONST 2 ('b')
10 LOAD_CONST 3 (2)
12 BUILD_MAP 1
14 STORE_NAME 1 (d1)
16 LOAD_NAME 2 (dict)
18 LOAD_NAME 0 (d0)
20 BUILD_TUPLE 1
22 LOAD_NAME 1 (d1)
24 CALL_FUNCTION_EX 1
26 STORE_NAME 3 (x)
28 LOAD_CONST 4 (None)
30 RETURN_VALUE

$ python -c "import dis; dis.dis(\"d0 = {'a': 1}; d1 = {'b': 2}; x =
d0.copy(); x.update(d1)\")"
1 0 LOAD_CONST 0 ('a')
2 LOAD_CONST 1 (1)
4 BUILD_MAP 1
6 STORE_NAME 0 (d0)
8 LOAD_CONST 2 ('b')
10 LOAD_CONST 3 (2)
12 BUILD_MAP 1
14 STORE_NAME 1 (d1)
16 LOAD_NAME 0 (d0)
18 LOAD_ATTR 2 (copy)
20 CALL_FUNCTION 0
22 STORE_NAME 3 (x)
24 LOAD_NAME 3 (x)
26 LOAD_ATTR 4 (update)
28 LOAD_NAME 1 (d1)
30 CALL_FUNCTION 1
32 POP_TOP
34 LOAD_CONST 4 (None)
36 RETURN_VALUE

$ python -m timeit "d0 = {'a': 1}; d1 = {'b': 2}; x = {**d0, **d1}"
1000000 loops, best of 3: 0.24 usec per loop

$ python -m timeit "d0 = {'a': 1}; d1 = {'b': 2}; x = dict(d0, **d1)"
1000000 loops, best of 3: 0.39 usec per loop

$ python -m timeit "d0 = {'a': 1}; d1 = {'b': 2}; x = d0.copy();
x.update(d1)"
1000000 loops, best of 3: 0.45 usec per loop
}}}

Obviously these are fairly contrived examples, and in many cases there can
be multiple calls to methods such as {{{dict.update()}}} or
{{{list.extend()}}}.

Here are examples of a number of changes that could be made:

{{{#!diff
# Unpack directly into initial definition:
-d = {...}
-d.update(extra)
+d = {..., **extra}

# Unpack instead of using dict() to combine (#1):
-d = dict(original, **extra)
+d = {**original, **extra}

# Unpack instead of using dict() to combine (#2):
-d = dict(original, ...)
+d = {**original, ...}

# Unpacking peforms a shallow copy like dict():
-d = dict(original)
-d.update(extra)
+d = {**original, **extra}

# Unpacking peforms a shallow copy like dict.copy():
-d = original.copy()
-d.update(extra)
+d = {**original, **extra}

# Unpacking peforms a shallow copy like copy.copy():
-import copy
-d = copy.copy(original)
-d.update(extra)
+d = {**original, **extra}

# More complex examples that become simple:
-d = dict(original, ...)
-d.update(extra or {})
+d = {**original, ... **(extra or {})}

# Unpacking for sets also makes things simple:
-s = {...}
-s.update(extra)
-s.update(override)
+s = {..., *extra, *override}

# Unpacking for lists also makes things simple:
-l = [...]
-l.extend(extra)
-l.extend(override)
+l = [..., *extra, *override]
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/28909>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Dec 8, 2017, 2:08:53 PM12/8/17
to django-...@googlegroups.com
#28909: Use unpacking generalizations added in Python 3.5
-------------------------------------+-------------------------------------
Reporter: Nick Pope | Owner: Nick Pope
Type: | Status: assigned
Cleanup/optimization |
Component: Core (Other) | Version: master
Severity: Normal | Resolution:
Keywords: unpacking | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* component: Uncategorized => Core (Other)
* stage: Unreviewed => Ready for checkin


--
Ticket URL: <https://code.djangoproject.com/ticket/28909#comment:1>

Django

unread,
Dec 11, 2017, 7:09:11 AM12/11/17
to django-...@googlegroups.com
#28909: Use unpacking generalizations added in Python 3.5
-------------------------------------+-------------------------------------
Reporter: Nick Pope | Owner: Nick Pope
Type: | Status: closed

Cleanup/optimization |
Component: Core (Other) | Version: master
Severity: Normal | Resolution: fixed

Keywords: unpacking | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham <timograham@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"d13a9e44ded4e93570c6ba42ec84e45ddca2505b" d13a9e4]:
{{{
#!CommitTicketReference repository=""
revision="d13a9e44ded4e93570c6ba42ec84e45ddca2505b"
Fixed #28909 -- Simplified code using tuple/list/set/dict unpacking.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/28909#comment:2>

Django

unread,
Dec 21, 2017, 9:05:38 PM12/21/17
to django-...@googlegroups.com
#28909: Use unpacking generalizations added in Python 3.5
-------------------------------------+-------------------------------------
Reporter: Nick Pope | Owner: Nick Pope
Type: | Status: closed
Cleanup/optimization |
Component: Core (Other) | Version: master
Severity: Normal | Resolution: fixed
Keywords: unpacking | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Graham <timograham@…>):

In [changeset:"f3a98224e6dd5f8846008512f281e452dc3b1909" f3a98224]:
{{{
#!CommitTicketReference repository=""
revision="f3a98224e6dd5f8846008512f281e452dc3b1909"
Refs #28909 -- Simplifed code using unpacking generalizations.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/28909#comment:3>

Django

unread,
Feb 26, 2018, 12:24:13 PM2/26/18
to django-...@googlegroups.com
#28909: Use unpacking generalizations added in Python 3.5
-------------------------------------+-------------------------------------
Reporter: Nick Pope | Owner: Nick Pope
Type: | Status: closed
Cleanup/optimization |
Component: Core (Other) | Version: master
Severity: Normal | Resolution: fixed
Keywords: unpacking | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by GitHub <noreply@…>):

In [changeset:"074a2f7f58cfab807ae72b09e634cad30a895369" 074a2f7f]:
{{{
#!CommitTicketReference repository=""
revision="074a2f7f58cfab807ae72b09e634cad30a895369"


Refs #28909 -- Simplifed code using unpacking generalizations.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/28909#comment:4>

Django

unread,
Sep 28, 2018, 9:57:32 AM9/28/18
to django-...@googlegroups.com
#28909: Use unpacking generalizations added in Python 3.5
-------------------------------------+-------------------------------------
Reporter: Nick Pope | Owner: Nick Pope
Type: | Status: closed
Cleanup/optimization |
Component: Core (Other) | Version: master
Severity: Normal | Resolution: fixed
Keywords: unpacking | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Graham <timograham@…>):

In [changeset:"8ef8bc0f64c463684268a7c55f3d3da4de066c0d" 8ef8bc0f]:
{{{
#!CommitTicketReference repository=""
revision="8ef8bc0f64c463684268a7c55f3d3da4de066c0d"


Refs #28909 -- Simplifed code using unpacking generalizations.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/28909#comment:5>

Reply all
Reply to author
Forward
0 new messages