One block of code works but the other does not. Which would make sense except the second block is the same as the first only with an operation written in shorthand. They are practically the same operation.
l = ['table'] i = []
for n in l: i += n print(i)
Output: ['t', 'a', 'b', 'l', 'e']
for n in l: i = i + n print(i)
Output:
TypeError: can only concatenate list (not "str") to list
What is causing this strange error?
Select the cells you want to check for duplicates. Note: Excel can't highlight duplicates in the Values area of a PivotTable report. Click Home > Conditional Formatting > Highlight Cells Rules > Duplicate Values.
To count the duplicates in an array: Declare an empty object variable that will store the count for each value. Use the forEach() method to iterate over the array. On each iteration, increment the count for the value by 1 or initialize it to 1 .
They don't have to be the same.
Using the +
operator calls the method __add__
while using the +=
operator calls __iadd__
. It is completely up to the object in question what happens when one of these methods is called.
If you use x += y
but x
does not provide an __iadd__
method (or the method returns NotImplemented
), __add__
is used as a fallback, meaning that x = x + y
happens.
In the case of lists, using l += iterable
actually extends the list l
with the elements of iterable
. In your case, every character from the string (which is an iterable) is appended during the extend
operation.
Demo 1: using __iadd__
>>> l = [] >>> l += 'table' >>> l ['t', 'a', 'b', 'l', 'e']
Demo 2: using extend
does the same
>>> l = [] >>> l.extend('table') >>> l ['t', 'a', 'b', 'l', 'e']
Demo 3: adding a list and a string raises a TypeError
.
>>> l = [] >>> l = l + 'table' [...] TypeError: can only concatenate list (not "str") to list
Not using +=
gives you the TypeError
here because only __iadd__
implements the extending behavior.
Demo 4: common pitfall: +=
does not build a new list. We can confirm this by checking for equal object identities with the is
operator.
>>> l = [] >>> l_ref = l # another name for l, no data is copied here >>> l += [1, 2, 3] # uses __iadd__, mutates l in-place >>> l is l_ref # confirm that l and l_ref are names for the same object True >>> l [1, 2, 3] >>> l_ref # mutations are seen across all names [1, 2, 3]
However, the l = l + iterable
syntax does build a new list.
>>> l = [] >>> l_ref = l # another name for l, no data is copied here >>> l = l + [1, 2, 3] # uses __add__, builds new list and reassigns name l >>> l is l_ref # confirm that l and l_ref are names for different objects False >>> l [1, 2, 3] >>> l_ref []
In some cases, this can produce subtle bugs, because +=
mutates the original list, whilel = l + iterable
builds a new list and reassigns the name l
.
BONUS
Ned Batchelder's challenge to find this in the docs
No.
7.2.1. Augmented assignment statements:
An augmented assignment expression like
x += 1
can be rewritten asx = x + 1
to achieve a similar, but not exactly equal effect. In the augmented version, x is only evaluated once. Also, when possible, the actual operation is performed in-place, meaning that rather than creating a new object and assigning that to the target, the old object is modified instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With