Skip to content

Instantly share code, notes, and snippets.

@scode
Created August 1, 2014 02:50
Show Gist options
  • Select an option

  • Save scode/ba6f7395ae7c039b4c75 to your computer and use it in GitHub Desktop.

Select an option

Save scode/ba6f7395ae7c039b4c75 to your computer and use it in GitHub Desktop.
Python is insane
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> l1 = [1, 2]
>>> l2 = l1
>>> l1
[1, 2]
>>> l2
[1, 2]
>>> l1 += [3]
>>> l1
[1, 2, 3]
>>> l2
[1, 2, 3]
>>> l1 = l1 + [4]
>>> l1
[1, 2, 3, 4]
>>> l2
[1, 2, 3]
@kwlzn

kwlzn commented Aug 1, 2014

Copy link
Copy Markdown

l1 += [3] is an append operation to an existing list (by reference).
l1 = l1 + [4] is a pointer reassignment of l1 to a new list, by expression (l1 + [4]).

these are two entirely different operations in python:

>>> l1 = l2 = [1,2]
>>> id(l1), l1, id(l2), l2
(4483639920, [1, 2], 4483639920, [1, 2])
## append by reference to the list referenced in l1.
>>> l1 += [3]
>>> id(l1), l1, id(l2), l2
(4483639920, [1, 2, 3], 4483639920, [1, 2, 3])
## reassign l1 to a new list created by the expression 'l1 + [4]'.
>>> l1 = l1 + [4]
>>> id(l1), l1, id(l2), l2
(4483639848, [1, 2, 3, 4], 4483639920, [1, 2, 3])

>>> l1 = l2 = [1,2]
>>> id(l1), id(l1 + [3])
(4483639848, 4483640136)

>>> l1 = l2 = [1,2]
## another way to append by reference.
>>> l1.append(3)
>>> id(l1), l1, id(l2), l2
(4483480896, [1, 2, 3], 4483480896, [1, 2, 3])

@kwlzn

kwlzn commented Aug 1, 2014

Copy link
Copy Markdown

use of the += operator invokes the type class' __iadd__() method which modifies in-place by reference (and retains the modified reference). mutable types do not implement __iadd__ (as they cannot modify in-place), in which case the += handler falls back to __add__ and returns a reference to the new value.

illustrating __iadd__ and __add__ behavior

>>> l1 = l2 = [1,2]
>>> id(l1), l1, id(l2), l2
(4346698280, [1, 2], 4346698280, [1, 2])
>>> x = l1.__iadd__([3])
>>> id(x), x, id(l1), l1, id(l2), l2
(4346698280, [1, 2, 3], 4346698280, [1, 2, 3], 4346698280, [1, 2, 3])
>>> x = l1.__add__([3])
>>> id(x), x, id(l1), l1, id(l2), l2
(4346698352, [1, 2, 3, 3], 4346698280, [1, 2, 3], 4346698280, [1, 2, 3])

behavior for immutable string type (invokes __add__ as illustrated above):

>>> l1 = l2 = 'xxx'
>>> id(l1), l1, id(l2), l2
(4346675152, 'xxx', 4346675152, 'xxx')
>>> l1 += 'yyy'
>>> id(l1), l1, id(l2), l2
(4346723184, 'xxxyyy', 4346675152, 'xxx')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment