3

Possible Duplicate:
How to clone a list in python?

I found some interesting results

a = [1, 2] 
b=a 
b.append(3) 
print a, b

#=> [1,2,3] [1,2,3]


a = [1, 2] 
b=a 
b += [3] 
print a, b

#=> [1,2] [1,2,3]

It seems like some operation have change the referenced value, some create a new. I remember in Ruby it can use ! to indicate which method have this destructive nature. Does python have the similar way to let me distinguish them? or providing a list to show all the most commonly used one?

Community
  • 1
  • 1
mko
  • 21,334
  • 49
  • 130
  • 191
  • `b += a` operator is the same as `b = b + a` where `+` is concatenation, which creates a new object. Python documentation is your only friend. – dzonder Oct 30 '12 at 08:44
  • @PaoloMoretti, I dont think it's a duplicate but the linked question is kind of a answer to this one. – Willy Oct 30 '12 at 08:45
  • @dzonder: Is this explicitly mentioned somewhere? Because according to the [data model docs](http://docs.python.org/2/reference/datamodel.html#object.__iadd__): *"These methods should attempt to do the operation in-place (modifying self) and return the result (which could be, but does not have to be, self)"*. But it might be different for sequence types... – Felix Kling Oct 30 '12 at 08:46
  • Unfortunately, I don't think there is any kind of indicator (except looking for `id(b) != id(a)` ). – lucasg Oct 30 '12 at 08:48
  • 6
    **Oh**, which Python version are you using? I get `[1, 2, 3] [1, 2, 3]` as output in Python 2.7.3. – Felix Kling Oct 30 '12 at 08:50
  • @FelixKling _"If a specific method is not defined, the augmented assignment falls back to the normal methods."_. I didn't find `__iadd__` in list methods in my Python environment. – dzonder Oct 30 '12 at 09:22
  • 2
    @dzonder: Yeah, I saw that too. I did not expect a version where `__iadd__` does not exist. Which version are you using? – Felix Kling Oct 30 '12 at 09:25
  • 5
    The syntax for augmented assignments was only added in 2.2 (http://www.python.org/getit/releases/2.2/NEWS.txt) and by then in-place `__iadd__` had already been implemented for `list`. So it seems no version of Python should exist where the `[1,2]+=[3]` would have to fall back to `[1,2]+[3]`. Something is weird. – max Oct 30 '12 at 09:47
  • 3
    I'm voting to close this question. It seems that what was posted here is not the actual results. – interjay Oct 30 '12 at 09:55

2 Answers2

1

Contrary to some existing answers here, the real reason actually the opposite. += is meant to be an in-place operator that modifies self in Python. But there's some catch to it.


For immutable types such as tuples and strings, my_tuple += (1, ) is equivalent to my_tuple = my_tuple + (1, ) which creates a new object then assigns it to my_tuple:

>>> my_tuple = (1,2,3)
>>> t = my_tuple
>>> t += (2,)
>>> t
(1, 2, 3, 2)
>>> my_tuple
(1, 2, 3)

This is because immutable types such as tuples and strings do not implement __iadd__ (you can check by dir(tuple) for example). And in this case it falls back to use __add__ instead. This will create a new object and assign it to the original variable.


For some mutable types such as lists and dictionaries, however, __iadd__ is implemented, and += will be calling it instead:

>>> inspect.getdoc(list.__iadd__)
'x.__iadd__(y) <==> x+=y'

>>> a = [1,2,3]
>>> b = a
>>> b += [4]
>>> b
[1, 2, 3, 4]
>>> a
[1, 2, 3, 4]

So for mutable types, this in-place operation is performed (by modifying self) and the original object will be updated.

K Z
  • 29,661
  • 8
  • 73
  • 78
  • 1
    Your last sentence seems incorrect. `list` does implement `__iadd__`, and `list.__add__` is not the same as `extend`. `list.__iadd__` is (almost) the same as `extend`. – interjay Oct 30 '12 at 09:37
  • @interjay you are right, it should be the `tuple` that does not have it implemented. I have updated my answer to correct it. Thanks for the catch! – K Z Oct 30 '12 at 10:24
0

There is no naming convention.

However, the use is that methods that modify the object return None, and those that create a new object will return said object.

Thomas Orozco
  • 53,284
  • 11
  • 113
  • 116