[python] 再来理解迭代器 生成器

1,原理 

iter,简单可以理解成完成的list对象

gen,实际通过next方法,没执行一次就 保留最新的结果

2,区别

(i for i in a)

[i for i in b]

3,使用场景

数据比较

4,技巧

yield 

 

#0629 iter and genalrator
'''
def is_iterable(param):
    try:
        iter(param)
        return True
    except TypeError:
        return False
params=[
    1234,
    '1234',
    [1,2,3,4],
    set([1,2,3,4]),
    {1:1,2:2,3:3,4:4},
    (1,2,3,4)
    ]
for param in params:
    print('{} is iterable? {}'.format(param,is_iterable(param)))
    
'''
# 显然除了 第一个是number,其他不管是  字符串,list ,set,还是dict等都是iterable的 

# 什么是生成器generator 呢 ?

'''
import os 
import psutil

def show_memory_info(hint):
    pid=os.getpid()
    p=psutil.Process(pid)
    
    info=p.memory_full_info()
    memory=info.uss/1024./1024
    print('{} use {} MB  '.format(hint,memory))
#show_memory_info('QQ.exe')
def test_iterator():
    show_memory_info('initing iterator')
    list_1=[i for i in range(10000000)]
    show_memory_info('after iterator initiated')
    print(sum(list_1))
    show_memory_info('after sum called')

def test_generator():
    show_memory_info('initing generator')
    list_2=(i for i in range(10000000))
    show_memory_info('after generator initiated')
    print(sum(list_2))
    show_memory_info('after sum called')    

%time test_iterator()
%time test_generator()
'''
####################### out put below##############################
'''
after iterator initiated use 429.62109375 MB  
49999995000000
after sum called use 429.62109375 MB  
Wall time: 1.46 s
initing generator use 41.23046875 MB  
after generator initiated use 41.23046875 MB  
49999995000000
after sum called use 41.43359375 MB  
Wall time: 826 ms
'''
# 直观感受就是 第一个使用内存多,而且要慢一点,据说 后者是在进行这种累加计算的时候,并不保留全部中间值,而是内次next之后就更新一下值 
# 
#'''
# 什么事OOM错误 
# 迭代器相对有限,生成器 可以一直next 下午

'''
M=[1,6,2,4,5,2,8,3,2]
print(*enumerate(M))
print(list(enumerate(M)))

# 传统方式
def index_normal(L,target):
    result=[]
    for i,num in enumerate(L):
        if num==target:
            result.append(i)
    return result
print(index_normal(M,2))
# 生成器方式

def index_generator(L,target):
    for i,num in enumerate(L):
        if num==target:
            yield i
print(*index_generator(M,2))
print (list(index_generator(M,2)))
# 看到这个的区别的 , 生成器不用定义 result 也不用返回, 当循环一直进行的情况下,就自动添加新的结果到结果集中,当然 要用一下 list 进行转换

'''
'''4

# 最后 上一个 有点抽象的, 作用是 判断a是否 是b的一个 子序列  
# 例子如下
def is_subsequence(a,b):
    b = iter(b)
    return all(i in b for i in a)
list0=[1,2,3,4,5]
list1=[1,3,4]
list2=[1,4,3]
print(is_subsequence(list1,list0))
print(is_subsequence(list2,list0))

'''

#'''5
def is_subsequence(a,b):
    b=iter(b)
    print(b)
    # 转型iter 没有数据变化
    gen=(i for i in a)
    print(gen)
    # 转型 gen,没有数据变化
    
    for i in gen:
        print(i)
    # 展示 gen的数据
    gen=((i in b ) for i in a)
    print(gen)
    # 如何理解, 
    # 这里 gen 相当于 把a的每个元素作为循环变量, 逐个在b里边进行比对,如果通过1一次以上的next获取,则返回true ,有一点不太理解的就是 每次
    
    for i in gen:
        print(i)
    
    return all(((i in b ) for i in a))
    # 这个 all 其实是把 整个a作为元素看看是否在b中,但是无论如何返回的都是否定的--?

list0=[1,2,3,4,5]
list1=[1,3,4]
list2=[1,4,3]
list3=[1,2,3,4,5]
print(is_subsequence(list1,list0))
print(is_subsequence(list2,list0))
print(is_subsequence(list3,list0))

#'''5

 

posted @ 2019-06-29 17:58  allen514519  阅读(147)  评论(0)    收藏  举报