迭代器,生成器

一、迭代器

Iterable可迭代的------>__iter__          

注:只要含有_iter_  方法的都是可迭代的

[].__iter__  迭代器------>__next__

注:通过next就可以从迭代器中一个一个获取值 

总结:

只要含有__iter__  方法都是可迭代的——>可迭代协议

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

print('__iter__' in dir( [].__iter__()))
print('__next__' in dir( [].__iter__()))

迭代器协议和可迭代协议

1)、可以被for循环的都是可迭代的

2)、可迭代的内部都有__iter__ 方法

3)、只要是迭代器,一定可迭代

4)、可迭代的__iter__ 方法就可以得到一个迭代器

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

for

只要是可迭代对象的时候,才能用for

当我们遇到一个新的变量,不确定能不能for循环的时候,就判断它是否可迭代

isinstance() 判断列表是不是可迭代的或是迭代器

迭代器的好处:

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

节省内存空间

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

def wahaha():
    for i in range(2000000):
        yield '娃哈哈%s'%i
g = wahaha()
count = 0
for i in g:
    count +=1
    print(i)
    if count > 50:
        break
print('*******',g.__next__())
for i in g:
    count +=1
    print(i)
    if count > 100:
        break
View Code

二、生成器

本质:迭代器

迭代器函数:执行之后会得到一个生成器作为返回值

1)、只要含有yeild关键字的函数都是生成器函数

2)、yelid不能和return公用且需要写在函数内  

def generator():
    print(1)
    yield 'a'
    print(2)
    yield 'b'
    yield 'c'
g = generator()
# for i in g:
#     print(i)
ret = g.__next__()
print(ret)
ret = g.__next__()
print(ret)
ret = g.__next__()
print(ret)
View Code

 生成器的特点:

1)、调用函数之后函数不执行,返回一个生成器

2)、每次调用next方法的时候会取到一个值

3)、直到取完最后一个,再执行next会报错

从生成器中取值的几个方法:

1)、next

2)、for

3)、数据类型的强制转换:占用内存 

三、生成器函数的进阶 

 send获取下一个值的效果和next基本一样,只是在获取下一个值的时候,给一个值的位置传递一个数据

使用send的注意事项

1)、send作用范围和next一样

2)、第一次使用生成器的时候,是用next回去下一个值

3)、最后一个yield不能接受外部的值

def generator():
    print(123)
    yield 1
    print(456)
    content=yield 2
    print("===",content)
    print(789)
    yield 

g=generator()
ret=g.__next__()
print("***",ret)
ret=g.__next__()
print("***",ret)
ret=g.send("hello")
print("***",ret)
ret=g.__next__()
print("***",ret)
View Code

生成器的应用

获取移动平均值

预激生成器的装饰器

获取移动平均值

四、生成器的表达式

列表推导式格式:
[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] #遍历之后挨个处理

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

列表推导式和生成器表达式:
1)、括号不一样
2)、返回的值不一样——>几乎不占用内存空间(生成器表达式)

列表推导式:
例1、
30以内所有能被3整除的数
ret = [i for i in range(30) if i%3 == 0]  #完整的列表推导式
g = (i for i in range(30) if i%3 == 0)  #完整的生成器推导式
print(ret)
View Code

例2、30以内所有能被3整除的数的平方


ret = [i*i for i in (1,2,3,4) if i%3 == 0]
ret = (i*i for i in range(30) if i%3 == 0)
print(ret)
View Code

例3、找到嵌套列表中名字含有两个‘e’的所有名字


names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
ret=[name for li in names for name in li if name.count("e")==2]
print(ret)     #['Jefferson', 'Wesley', 'Steven', 'Jennifer']
View Code
字典推导式
例1、将一个字典的key和value对调
mcase = {'a': 10, 'b': 34}
ret={mcase[k]:k for k in mcase}
print(ret)     #{10: 'a', 34: 'b'}
View Code

例2、合并大小写对应的value值,将k统一成小写

mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
ret={k.lower():mcase.get(k.lower(),0)+mcase.get(k.upper(),0)for k in mcase}
print(ret)     #{'b': 34, 'a': 17, 'z': 3}
View Code

集合推导式,自带去重效果

squared={i**2 for i in [-1,1,3]}
print(squared)    #{1, 9}
View Code
 
 
原文地址:https://www.cnblogs.com/gaoya666/p/8178886.html