目录
1. 元组与列表的异同
(1)元组和列表都属于有序序列,都支持使用双向索引访问其中的元素,以及使用count() 方法统计指定元素的出现次数和index() 方法获取指定元素的索引,len()、map()、filter()等大量内置函数和+、in等运算符也都可以作用于元组和列表。
(2)元素属于不可变序列,不可以直接修改元组中元素的值,也无法为元组增加或删除元素。
(3)元组没有提供append()、extend()和insert()等方法,无法向元组中添加元素;同样,元组也没有remove() 和pop()方法,也不支持对元组元素进行del操作,不能从元组中删除元素,而只能使用del命令删除整个元组。
(4)元素和列表都可以通过切片来访问里面的元素。
(5)Python内部对元组做了大量优化,访问速度比列表更快。如果定义了一系列常量值,仅对它们进行遍历,而不需要对其元素进行修改,那么建议使用元组而不用列表。
(6)元组在内部不允许修改其元素的值,从而使代码更加安全,例如调用函数时使用元组传递参数可以防止在函数中修改元组,而使用列表很难保证这一点。
(7)元组可作为字典的键,也可以作为集合的元素。而列表不能作为字典的键使用,也不能作为集合中的元素。
2. Python的生成器
生成器是Python的一种非常重要的结构对象,其实质就是迭代器,语法格式如下:
(表达式 for 变量 in 序列或迭代对象)或:
(表达式 for 变量 in 序列或迭代对象 if 条件表达式)
表示:从序列或迭代对象中,生成满足条件的、表达式的值,返回一个生成器迭代对象。其中,if条件表达式是可选的。
从语法上看,它与列表推导式非常相似:除了定界符不同(列表推导式用方括号[ ]),里面的格式完全一样。但是,两者的本质及效率方面完全不同,主要表现在:
生成器返回的是一个生成器迭代对象,它具有惰性机制,即里面的元素只有在访问时才生成值,且一经访问,立即释放,占用内存少,效率高,适合处理大数据。而列表推导式返回的是一个列表,一次性加载,比较耗内存。
与其他迭代器一样,生成器对象的元素不能直接访问,可以根据需要将其转换为列表或元组,也可以使用生成器对象的__next__()方法或者内置函数next()进行遍历,或者直接使用for循环来遍历其中的元素。
(1)使用生成器对象__next__()方法或内置函数next()进行遍历,其特点是:访问一次,才在内存生成一次值,已访问过的元素立即释放内存,同时指向下一个元素。
L=[(i+1)**2 for i in range(6)] #创建列表推导式,L为列表,一次性全部在内存生成
#L=[1,4,9,16,25,36],当数据量大时,耗费内存
G=((i+1)**2 for i in range(6)) #创建生成器对象,不可直接访问
type(G) #<class'generator'>
tuple(G) #将G转换为元组:(1,4,9,16,25,36)
list(G) #生成器对象一旦访问结束,便全部释放,没有元素了
#输出:空列表对象[ ]
G=((i+1)**2 for i in range(6))
G.__next__() #使用生成器对象的__next__()方法获取元素:1
G.__next__() #获取下一个元素:4
next(G) #使用内置函数next()获取生成器对象中的元素:9
(2)使用 for 循环直接迭代生成器对象中的元素。
g=((i+1)**2 for i in range(6)) #创建生成器对象
for item in g: #循环遍历生成器对象中的元素
print(item,end=' ')
(3)访问过的元素不再存在。
x=filter(None,range(10)) #filter对象也具有生成器迭代的特点
type(x) #<class'filter'>
2 in x #True
list(x) #前面2个元素已经访问而被释放:[3,4,5,6,7,8,9]
x=map(str.range(8)) #map对象也具有生成器迭代的特点
'0' in x #返回True,遍历一次后,'0'在x中已经被释放
'0' in x #False