引用VS拷贝
赋值操作总是储存对象的引用,而不是对象的拷贝。赋值操作会产生相同对象的多个引用,在原处修改可变对象时,可能会影响程序中其他地方对相同对象的其他引用。
拷贝方法:
- L[:]复制序列
- 字典copy方法(X.copy())复制字典
- 内置函数(如list)生成拷贝(list(L))
- copy标准库模块生成完整拷贝
**注意:**无条件值的分片以及字典copy方法只能做顶层复制,不能复制嵌套的数据结构。使用标准的copy模块,copy.deepcopy(Y)对任意嵌套对象Y做完整的复制
并行遍历:zip和map
内置zip函数让我们使用for循环来并行使用多个序列,在基本运算中,zip会取得一个或多个序列为参数,然后返回元组列表,将这些序列中的并排的元素配成对。
L1 = [1,2,3,4]
L2 = [5,6,7,8]
zip(L1,L2)#object
list(zip(L1,L2))#[(1,5),(2,6),(3,7),(4,8)]
for (x,y) in zip(L1,L2):
print(x,y,'--',x+y)
当参数长度不同时,zip会以最短序列的长度为准来截断所得到的元组。
和zip一样,map是python3.0中的一个值生成器,因此必须传递给list以一次性收集其结果)
list(map(ord,'spam'))#[115,112,97,109]
#对键赋值来创建字典
list(zip(keys,vals)#[('spam',1),('eggs',3),('toast',5)]
enumerate根据相对位置来配对可迭代对象中的项,filter选择一个函数为真的项reduce针对可迭代对象中的成对的项运行一个函数。
列表解析
列表解析在一个序列的值上应用一个任意表达式,将其结果收集到一个新的列表中并返回,从语法上来说,列表解析由方括号封装起来【提醒构造列表】,其形式是在方括号中编写一个表达式,其中的变量,在后面跟着的像一个for循环的头部一样的语句,python将这个表达式的应用循环中每次迭代的结果收集起来。
res = [ord(x) for x in 'spam']
[x ** 2 for x in range(10)]
[x for x in range(5) if x%2 == 0]
list(filter((lambda x: x%2 ==0),range(5)))
res = []
for x in range(5):
if x % 2 == 0:
res.append[x]
还可以在列表解析中编写任意数量的嵌套for循环
res = [x+y for x in [0, 1, 2] for y in [100, 200, 300]]
[(x,y) for x in range(5) if x%2 ==0 for y in range(5) if y%2 ==1] #if分句过滤每个序列中需要迭代的元素
重访迭代器:生成器
延迟结果创建,需要时才产生结果,而不是立即产生结果
- 生成器函数:编写为常规的def语句,但是使用yield语句一次返回一个结果,在每个结果之间挂起和继续它们的状态
- 生成器表达式类似于列表解析,但返回按需产生结果的一个对象,而不是立即产生结果
不会一次性构造一个列表,节省了内存空间,且允许计算时间分散到各个请求
生成器函数:yield return
状态挂起
生成器函数自动在生成值的时刻挂起并继续函数的执行。由于生成器函数在挂起时保存的状态包含它们的整个本地作用域,当函数恢复时,其本地变了保持了信息并使其可用。
生成器yields一个值,而不是返回一个值,yield语句挂起该函数并向调用者发送回一个值,但是保留足够的状态使函数能够从它离开的地方继续。
扩展生成器函数协议:next
send必须直接作为生成器对象的方法来调用,这些额外的方法只是在内置的生成器对象上实现,而__next__方法应用于所有的可叠戴对象(包括内置类型和用户定义的类)
生成器表达式:迭代器+列表解析
从语法上来讲,生成器表达式就像一般的列表解析一样,但是它们是括在圆括号中而不是方括号中的;从执行过程上来讲,生成器表达式不实在内存中构建结果,而是返回一个生成器对象,这个对象将会支持迭代协议并在任意的迭代语境的操作中。
一般不会机械得使用next迭代器来操作生成器表达式,for循环会自动触发
for num in(x**2 for x in range(4)):
print('%s',num)
生成器表达式大体上可以认为是对内存空间的优化,不需要像列表解析一样,一次构造出整体结果列表。在实际中运行起来可能稍慢,对可能只对于非常大的结果集合的运算来说是最优的选择
生成器函数VS生成器表达式
G = (c * 4 for c in 'SPAM') #表达式
list(G)
def timesfour(S): #函数
for c in S:
yield c * 4
G = timesfour('SPAM')
list(G)
生成器是单迭代器对象,只支持一次活跃迭代【不像一些内置类型】