python中的迭代对象,迭代器,生成器

python中的迭代对象,迭代器,生成器

  1.python中迭代对象
    
  2.Python中迭代器
    
  3.python的函数的执行图

在这里插入图片描述在执行上述代码时,python解释器(python.exe)会用一个叫PyEval_EvalFrameEx()(C函数)会执行funct1函数,首先会创建栈帧(stack_frame上下文)当func1调用子函数func2又会创建一个栈帧,(看成一对象),所有的栈帧都是分配在堆内存上(堆内存特点:只要不释放,一直存在堆内存中)这就决定了栈帧可以独立于调用者

  4.python中的生成器
    1.概念:
        生成器函数,函数中只要有yield关键字
    2.产生:
        生成器对象,在python编译字节码的时候产生
    3.原理:
        生成器函数在普通函数中Heap memery进行了进一步的封装,具体看下图
在这里插入图片描述

def gen_func():
    yield 3
    name = "body"
    yield 5
    age = 25
    return "gen_func"


gen = gen_func()
print(dis.dis(gen))
print(gen.gi_frame.f_lasti)
print(gen.gi_frame.f_locals)
next(gen)
print(gen.gi_frame.f_lasti)
print(gen.gi_frame.f_locals)
next(gen)
print(gen.gi_frame.f_lasti)
print(gen.gi_frame.f_locals)

输出:

 20           0 LOAD_CONST               1 (3)
              2 YIELD_VALUE
              4 POP_TOP

 21           6 LOAD_CONST               2 ('body')
              8 STORE_FAST               0 (name)

 22          10 LOAD_CONST               3 (5)
             12 YIELD_VALUE
             14 POP_TOP

 23          16 LOAD_CONST               4 (25)
             18 STORE_FAST               1 (age)

 24          20 LOAD_CONST               5 ('gen_func')
             22 RETURN_VALUE


None
-1
{}
2
{}
12
{'name': 'body'}

  3.python中的生成器(进阶)
      生成器的三个方法:
            1.send()
                        代码块:

def gen_func():
	html = yield "http://www.xxxxxx.com"
	print(html)
	yield 3
	yield 4 
	return "csdn"
if __name__ == "__main__":
	gen = gen_func()
	"""
	#在此处调用send发送非None值前,必须启动一下生成器
	调用的方法有两种:
		1.gen.send(None)
		2.next(gen)
	"""
	url = gen.send(None)
	print(url)
	number = gen.send("cccc")
	print(number)

输出:

http://www.xxxxxx.com
cccc
3

总结:
      send方法的作用:
            可以传递值进入生成器内部,同时还可以启动生成器执行下一个yield
 
            1.close()
                        代码块:

def gen_func():
	yield 2    #代码1的位置
	yield 3	   #代码2的位置
	return "csdn"
if __name__ == "__main__":
	gen = gen_func()
	print(next(gen))
	gen.close()
	"""
	注释:
		当执行close()方法时,会在代码1的位置抛出一个GeneratorExit的异常,所以当在close()后在执行next(gen)方法时程序会报错,错误类型为GeneratorExit
		GeneratorExit的异常时继承BaseException的
	"""

 
            3.throw()
                        代码块:

def gen_func():
	try:
		yield 1   #代码1位置
	except Exception as e:
		print(e)
	yield 2   #代码2位置
	yield 3	  #代码3位置
	return "csdn"
if __name__ == "__main__":
	gen = gen_func()
	print(next(gen))
	a = gen.throw(Exception, "error")
	print(a)
	print(next(gen))

输出:

1
error
2
3
"""
	由输出结果可以看出throw()方法可以在当前代码位置抛出异常,并重启生成器执行下一个yield
"""

  4.python中的生成器之间 >>>>>>> yield from
    代码块:

def g1(gen):
	yield from gen
def main():
	g = g1(gen)
	g.send(None)
"""
概念:
	1.main为调用方
	2.g1是委托生成器
	3.gen子生成器
作用:
	yield from会在调用发方和子生成器间建立一个双向通道
"""

  
yield from 在调用方和子生成器建立双向通道的例子如下:

final_result = {}                                  
                                                   
                                                   
def sales_sum(pro_name):                           
    total = 0                                      
    nums = []                                      
    while True:                                    
        x = yield     #表示只接收send来值                             
        print(pro_name + "销量:", x)                 
        if not x:                                  
            break                                  
        total += x                                 
        nums.append(x)                             
    return total, nums                             
                                                   
                                                   
def middle(key):                                   
    while True:                                    
        final_result[key] = yield from sales_sum(ke
        print(key + "完成")                      
                                                   
                                                   
def main():                                        
    data_sets = {                                  
        "鞋": [1200, 1300, 5000],                   
        "手机": [28, 53, 100, 90],                   
        "裤子": [280, 560, 776, 10]                  
    }                                              
    for key, data_set in data_sets.items():        
        print("start key:", key)                   
        m = middle(key)                            
        m.send(None)  # 预激活middle协程                
        for value in data_set:                     
            m.send(value)  # 给协程传递一组数据, 此时发送的value值直接被 sales_sum方法中的x接收      
        m.send(None)                               
    print("final_result:", final_result)           
                                                   
                                                   
if __name__ == '__main__':                         
    main()                                         
                                                   

     yield from所处理的逻辑
          处理了很多异常的逻辑具体如下:
                    1.子生成器生产的值,都是直接传给调用方,通过send()发送的值都是直接传递给子生成器的,如果发送的None,会调用子生成器的__next__方法,如果不是None, 会调用子生成器的send()方法
                    2.子生成器退出的时候,最后return会触发一个StopIteration(EXPR)异常
                    3.yield from表达式的值,是子生成器终止时传递给StopIteration异常的第一个参数
                    4.如果调用的时候出现StopIteration异常,委托生成器会恢复运行,同时其他异常会向上"冒泡"
                    5.传入委托生成器的异常里,除了GeneratorExit之外,其他的所有异常全部传入给子生成器的throw()方法,如果调用throw()的时候出现StopIteration异常,那么就恢复委托生成器的运行,其他异常全部向上"冒泡"
                    6.如果在委托生成器上调用close()或传入GenerationExit异常,会调用子是生成器的close()方法,没有的话就不会调用,如果在调用close()的时候抛出了异常,那么就向上"冒泡",否则的话委托生成器会抛出GenerationExit异常

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值