Python——迭代器和生成器

1. 迭代器

(1)迭代器——iterator

  [].__iter__(),通过__next__方法就可以从迭代器中一个一个取值

(2)可迭代的——iterable

  只要含有__iter__方法的都是可迭代的

(3)相关协议

  可迭代协议 —— 只要含有__iter__方法的都是可迭代的,可以被for循环的都是可迭代的

  迭代器协议 —— 内部含有__next__和__iter__方法的就是迭代器

(4)是否是迭代器的判断

  以下几种情况可能是迭代:

  <1>.iterator——print([].__iter__()) #<list_iterator object at 0x00000277E7E0CE10>

  <2>.可迭代对象——print(range(10))

  <3>.直接给内存地址

  只有 是可迭代对象的时候,才能有for循环——for循环其实就是在使用迭代器

  遇到新变量,不确定能不能for循环的时候,可以判断其是否可迭代

(5)迭代器和可迭代的对比

  迭代器一定可迭代,可迭代的不一定是迭代器

  可迭代的.__iter__()方法就可以得到一个迭代器

  迭代器中的__next__方法可以一个一个的获取值

(6)迭代器的好处

  <1>从容器类型中一个一个的取值,会把所有值都取到

  <2>节省内存空间

    迭代器并不会在内存中占用一大块内存,而是随着循环每次生成一个,或者每次next每次生成一个

2. 生成器

(1)本质

  生成器的本质就是迭代器

(2)生成器函数

  含有关键字yield的函数就是生成器函数,关键字yield只能写在函数内部,不会结束函数,且不能与return共用

def generator():
    print(1)
    yield 'a'
    print(2)
    yield 'b'
# 生成器函数:执行之后会得到一个生成器作为函数的返回值
ret = generator()
print(ret)
print(ret.__next__())
print(ret.__next__())

运行结果:

 

特点:

  调用函数的时候函数不执行,返回一个生成器
  每次调用next方法的时候会取到一个值
  直到取完最后一个,在执行就会报错

(3)各种推导式

表达式格式:

  遍历操作:[每一个元素/和元素相关的操作 for 元素 in 可迭代数据类型]

  筛选功能:[满足条件的元素相关的操作 for 元素 in 可迭代数据类型]

  <1> 生成器表达式

老母鸡 = ('鸡蛋%s'%i for i in range(10))    #生成器表达式
print(老母鸡)
forin 老母鸡:
    print(蛋)
# 面试——取一个next,for循环执行一次
g = (i*i for i in range(10))
print(g.__next__())    # 1:取一个next,for循环执行一次
print(g.__next__())    # 4:取一个next,for循环执行一次
print(g.__next__())    # 9:取一个next,for循环执行一次
print(g.__next__())    # 16:取一个next,for循环执行一次

  <2> 列表推导式

# 30以内所有能被3整除的数
ret = [i for i in range(30) if i%3 == 0]
print(ret)  #[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]

# 30以内所有能被3整除的数的平方
ret = [i*i for i in range(30) if i%3 == 0]
print(ret)  #[0, 9, 36, 81, 144, 225, 324, 441, 576, 729]

#找嵌套列表中名字含有两个e的名字
names = [['tom','billy','jefference','aneedhg'],
         ['alice','jill','ehdjbse']]
ret = [name for lst in names for name in lst if name.count('e') == 2]
print(ret)  #['aneedhg', 'ehdjbse']

  <3> 字典推导式

# 将一个字典的key和value对调
mcase = {'a':10,'b':34}
mcase_frequency = {mcase[k]:k for k in mcase}
print(mcase_frequency)  #{10: 'a', 34: 'b'}

# 合并大小写对应的value的值,将k统一写成小写
mcase = {'a':10,'b':34,'A':7,'Z':3}
mcase_frequency = {k.lower():mcase.get(k.lower(),0 )+mcase.get(k.upper(),0)for k in mcase}
print(mcase_frequency)  #{'a': 17, 'b': 34, 'z': 3}

  <4> 集合推导式

# 计算列表中每个值的平方(集合推导式自带结果去重功能)
squared = {x**2 for x in [1,-1,2]}
print(squared)  #{1, 4}

生成器表达式和其他各种表达式的区别:

  括号不一样

  返回值不一样(生成器表达式几乎不占用内存)

(4)生成器的优点

  延迟计算,一次返回一个结果

 

猜你喜欢

转载自www.cnblogs.com/xc-718/p/9700616.html