列表生成式
L1 = ['Hello', 'World', 18, 'Apple', None]
L2 = [x.lower() for x in L1 if isinstance(x,str)]
print(L2)
if L2 == ['hello', 'world', 'apple']:
print('测试通过!')
else:
print('测试失败!')
生成器
在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]
改成()
,就创建了一个generator。generator保存的是算法,每次调用next()
,就计算出下一个元素的值,直到计算到最后一个元素。当元素过多的时候正确的调用方法是使用for
循环,因为generator也是可迭代对象我们创建了一个generator后,基本上永远不会调用next()
,而是通过for
循环来迭代它,并且不需要关心StopIteration
的错误。
练习:使用生成器方法,输出杨辉三角
def generate_pascal_triangle():
row = [1]
while True:
yield row
row = [1] + [row[i] + row[i+1] for i in range(len(row)-1)] + [1]
# 创建生成器对象
gen = generate_pascal_triangle()
# 打印前10行
for _ in range(10):
print(next(gen))
核心代码,row = [1] + [row[i] + row[i+1] for i in range(len(row)-1)] + [1]这一句该如何理解呢?
首先,我们有[1]
,这是每一行的开头和结尾都是1的规律。
然后,我们有[row[i] + row[i+1] for i in range(len(row)-1)]
,这是计算每一行中间的数字的规律。它使用了列表推导式的语法,遍历了row
列表的索引,从0到len(row)-1
(不包括len(row)-1
),并计算每两个相邻元素的和。这样,我们得到了每一行中间的数字。
最后,我们有[1]
,这是每一行的结尾都是1的规律。
将上述三个部分连接起来,我们就得到了帕斯卡三角形的下一行。
举个例子,假设当前行是[1, 3, 3, 1]
,那么下一行就是[1] + [1+3, 3+3, 3+1] + [1]
,即[1, 4, 6, 4, 1]
。
为什么list、dict、str等数据类型不是Iterator?
作者:wodeliang
链接:https://www.jianshu.com/p/7ec58f295c75
因为Python的对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
小结
凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
Python的for循环本质上就是通过不断调用next()函数实现的。