Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> To reduce memory usage, you can use in-place operations like +=

btw, I think it's a design flaw in python that `a += b` is not always equivalent to `a = a + b`.



As someone who has never used Python seriously I have to ask... why not?


As an optimisation, you can override += separately from +. A pretty well known oddity related to this is:

    >>> a = ([0],) # a tuple (immutable) containing a list (mutable)
    >>> a[0] = a[0] + [1]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: 'tuple' object does not support item assignment
    >>> a
    ([0],)
    >>> a[0] += [1]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: 'tuple' object does not support item assignment
    >>> a
    ([0, 1],)
Though to be fair, technically nothing prevents "+" from mutating either operator (it'd just get you tarred and feathered).


Wait...did it throw an exception, yet still add the item to the list?

EDIT: Tried it myself. Sure enough, it throws the exception, but still adds the item. This seems like a bug.

EDIT Part 2: I understand now. `a[0] += [1]` is internally translated to `a[0] = a[0].__iadd__([1])`. The right-hand side is interpreted, mutating a[0] in-place as expected. But then the re-assignment happens, which throws the exception since you're trying to re-assign a value in a tuple, which is immutable.


You got it, that’s why it’s so odd.


It's because of Python's distinction (enforced mainly by convention) between references and value types.

If you are using a value type, `__iadd__`[1] can return a new value. So:

   x = 5
   y = x
   x += 3
   y is not x and y == 5
But if you're using a reference type, it is allowed to mutate the reference and return the original reference.

   x = [1, 2]
   y = x
   x += [3, 4]
   y is x and y == [1, 2, 3, 4]
[1]: https://docs.python.org/3/reference/datamodel.html#object.__...


Python defines += as the __iadd__ method which is sometimes mutating, i.e. if the object being assigned to is mutable or not.


Because I once learned that `a += b` is just a shortcut for `a = a + b`, just a syntax sugar. Now I have to constantly remind myself that it's not the case in python.

edit: I might have misunderstood your question. If you meant "why it's not equivalent" please see the falkaer's answer.


It's not equivalent but honestly this gotcha with lists will only show up in bad code and interview quizzes (i.e. bad code).


They aren't equivalent in C++ either.


My C++ is a bit rusty. Does it manifest itself in the standard library as well? The problem with python (in my view) is that this behaviour is implemented in the standard library and therefor propagates to the 3rd-party libraries by convention.


> Does it manifest itself in the standard library as well?

Yes. For example for std::string `a = a + b;` will (at least notionally) create a temporary string and then use the assignment operator. `a += b;` will not do this.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: