列表生成式
列表生成式是 python 内置的非常简单却强大的可以用来创建list的生成式。
有这样一个需求:
l1 = [1,2,3,4,5,6,7,8,9] 循环每个元素加1
l1 = [1,2,3,4,5,6,7,8,9]
# 使用列表生成式将列表中的各个元素加1
list_num = [x+1 for x in l1]# 这里就是一个列表生成式
print(list_num)
列表生成式可以用一行语句代替循环生成上面的list
迭代器
迭代器表面上看是一个数据流对象或容器,当使用其中的数据时,每次从数据流中取出一个数据,直到数据被取完,而且数据不会被重复使用。
从代码的角度来看,迭代器是实现了迭代器协议方法的对象和类。
迭代器协议方法主要是两个:
__iter__(): 该方法返回对象本身,它是for语言使用迭代器的要求,只要函数含有__iter__就可以说这个函数是可迭代的;
__next__(): 该方法用于返回容器中下一个元素或数据。当容器中的数据用尽时,应该引发 StopIteration 异常一个类只要具有这两种方法,就可以称之为 迭代器,也可以说是可迭代的。
s1 = 'hello world'
print('__iter__' in dir(s1))
print('__next__' in dir(s1))
# 字符串s1包含 __iter__ 方法且不包含__next__方法,所以字符串 s1 只是一个可迭代的类型,并不是一个迭代器
# 执行结果:
# True
# False
s1 = 'hello world'
s2 = s1.__iter__() # 将可迭代类型转换为 迭代器 使用 __iter__()
print('__iter__' in dir(s2))
print('__next__' in dir(s2))
# 使用 __iter__()方法将 s1 字符串转换为迭代器,迭代器既有__iter__方法,又有 __next__方法
# 执行结果:
# True
# True
自定义一个迭代器必须满足:
类中必须要定义 __iter__ 方法和 __next__方法
# 自定义一个迭代器:
class My_iterator(object):
def __init__(self, x, max):
self.mul, self.x = x, x
self.xmax = max
def __iter__(self):
return self
def __next__(self):
if self.x and self.x !=1:
self.mul = self.mul + self.x
if self.mul < self.xmax:
return self.mul
else:
raise StopIteration
if __name__ == '__main__':
myite1 = My_iterator(2, 100)
for i in myite1:
print(i)
迭代器一定是可迭代的, 但是可迭代的不一定是迭代器
生成器
使用生成器可以生成一个值的序列用于迭代,并且这个值的序列不是一次生成的,而是使用一个,再生成一个,可以使得程序节约大量内存。
生成器对象是通过yield关键字定义的函数对象,因此生成器也是一个函数。生成器用于生成一个值的序列,以便在迭代中使用。
自定义生成器:
def foo():
print('1111')
yield 1
print('22222')
yield 2
f = foo()
print('type f:', type(f))
print(f.__next__())
print(f.__next__())
# 执行结果:
# type f:
# 1111
# 1
# 22222
# 2
执行流程如下图:
需要注意的是 yield 是生成器中的关键字,生成器在实例化的时候并不会立即执行,而是等待调用其__next__()方法之后才开始运行,当再次调用__next__()方法会在第一次yield返回值的最后开始执行,不断的调用__next__()方法,直到最终返回 StopIteration 异常为止。
实例1:移动平均值
#移动平均值
deffoo():'''sum 计算总和
count 计算有几个数
avg 平均数
:yield: 返回计算出的平均数'''sum=0
count=0
avg=0whileTrue:
num= yield avg #接收num,返回avg
sum +=num
count+= 1avg= sum /count
f=foo()
next(f)
ret= f.send(10)print(ret)
ret= f.send(20)print(ret)
ret= f.send(30)print(ret)
ret= f.send(40)print(ret)#执行结果:#10.0#15.0#20.0#25.0
移动平均值