1. A puzzle about +=

# Increment assignment: A +=b calls the __iadd_ method (add in place), and a=a+b calls the __add__ method
>>> t=(1.2[2.3])
>>> t[2=] + [4.5]
Traceback (most recent call last):
  File "<stdin>", line 1.in <module>
TypeError: 'tuple' object does not support item assignment
>>> t
(1.2[2.3.4.5])
Delta assignment is not an atomic operation to decompose t[2]+=[4,5] into 2 steps: 1 ️temp=[2,3], temp+=[4,5], a variable object can perform this operation 2 discount t[2]=temp. Since t is a tuple, an immutable object will report an error. ' ' 'The solution>>> t[2].extend([4.5])
>>> t
(1.2[2.3.4.5])
>>> t=(1.2[2.3])
>>> t[2].append([4.5])
>>> t
(1.2[2.3[4.5]])
Copy the code

The delta assignment operators +=, *=. For incremental addition, __iadd__ is called first, or __add__ is called if there is no such method. The STR immutable object is an exception. Because string += is so common, Cpython optimizes it so that when it initializes memory for STR, it has extra expandable space, so that incremental operations don’t involve copying the original string to a new location.

2. Variable scope

>>> b=6
>>> def f1(a) :
.   print a
.   print b
.   b=9.>>> f1(3)
3
Traceback (most recent call last):
  File "<stdin>", line 1.in <module>
  File "<stdin>", line 3.in f1
UnboundLocalError: local variable 'b'Referenced before the assignment -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- why complains, rather than the normal output3  6When python compiles the body of a function, b is judged to be local because it is assigned a value in the body. The variable b is referenced before assignment, so an error is reported. If no value is assigned to b in the function body, b is considered a global variable.Copy the code

3. Avoid mutable objects as parameter defaults

# -*- coding: utf-8 -*-
def ad(nam,abs= []) :
    if abs= =None:
        abs= []abs.append(nam)
    return abs

print ad('xxx')
print ad('cx')
-----------------------out
['xxx']
['xxx'.'cx']  # expect output ['cx']The first output shares the same list as the second output. To get the desired result, take the parametersabsThe default isNone
Copy the code

4. The derived type

def demo() :
    for i in range(4) :yield i

g=demo()

g1=(i for i in g)
g2=(i for i in g1)

print(list(g1))
print(list(g2))
------------------out----why
[0.1.2.3[] ---------------- splitter linedef add(n,i) :
    return n+i
def test() :
    for i in range(2) :yield i
g=test()
for n in [1.2]:
    g=(add(n,i) for i in g)
print(list(g))
----------out------why
[4.5] ----------------------------- splitter (delayed binding)def create_multipliers() :
    return [lambda x : i * x for i in range(5)]
for multiplier in create_multipliers():
    print(multiplier(2() ---------------------out8 8 8 8 8Expectations:0 2 4 6 8-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --def create_multipliers() :
    return [lambda x,i=i: i * x for i in range(5)]
for multiplier in create_multipliers():
    print(multiplier(2))
Copy the code

5. Data overlay

 
>>> lists = [[]] * 3

>>> lists

[[], [], []]

>>> lists[0].append(3)

>>> lists

[[3], [3], [3]]
Copy the code

The resulting data is actually multiple references to the data, not copies

>>> lists = [[] for i in range(3)]

>>> lists[0].append(3)

>>> lists[1].append(5)

>>> lists[2].append(7)

>>> lists

[[3], [5], [7]]
Copy the code