1. python中的普通函数是怎么运行的?

当一个python函数在执行时,它会在相应的python栈帧上运行,栈帧表示程序运行时函数调用栈中的某一帧。想要获得某个函数相关的栈帧,则必须在调用这个函数且这个函数尚未返回时获取,可能通过inspect模块的currentframe()函数获取当前栈帧。

栈帧对象中的3个常用的属性:

  • f_back : 调用栈的上一级栈帧
  • f_code: 栈帧对应的c
  • f_locals: 用在当前栈帧时的局部变量;

比如:

更进一步讲, 标准的python解释器是用C语言写的,通常称作CPython, 当执行一个python函数时,解释器中的C函数 PyEval_EvalFrameEx() 就会被调用,它来处理python 代码的字节码, 它的参数为对于python函数的栈帧 object,即上面例子中的 x就是一个栈帧对象。

举例说明函数是如何运行的?

使用dis模块查看一下函数foo()的字节码(看不懂内容没事,其它有规律):

运行过程:

解释器调用 C函数 PyEval_EvalFrameEx()运行foo()的字节码,它的参数为foo()对应的栈帧对象,运行位置为foo()对应的栈帧; 在运行过程中,遇到 CALL_FUNCTION 时,它会为函数bar()生成新的栈帧,然后又调用一个 PyEval_EvalFrameEx() 运行bar()对应的字节码,……,如此递归,然后一层层的返回;

2. 对于python中栈帧:

在python中的栈帧其实是在解释器的堆上分配内存的,所以,在一个python函数运行完成后,它的栈帧的仍然存在,并没有消失,下面例子说明了(当func函数运行完成后,我们然后可以访问到它对应的栈帧):

3. python中的生成器函数是怎么运行的?

对于函数与生成器函数的区别在于生成器中有yield表达式, 它们的co_flags是不相同的:

  • function没有*args或**kw时,func.__ code__.co_flags=67;
  • function有*args没有**kw时,func.__ code__.co_flags=71;
  • function没有*args有**kw时,func.__ code__.co_flags=75;
  • function既有*args也有**kw时,func.__ code__.co_flags=79;
  • function是一个generator时,func.__ code__.co_flags=99.

当运行一个生成器函数时,它会生成一个生成器

上面例子中生成了两个生成器a与b, 每一个生成器都有两个常用的属性,分别为gi_frame与gi_code, 不同的生成器的gi_code是相同的,对应生成器函数的字节码,然而它们的gi_frame是不相同的,所以,不同的生成器可以分别运行,并且互不干扰;

对于每一个栈帧又都有一个指针f_lasti,它指向了最后执行的命令,在一开始没有执行时,它的值为-1;

当生成器执行到最后时,它就产生一个 StopIteration 异常,然后就停止了,当生成器函数中有return时, 这个异常的值就是return的值,如果没有return,异常的值为空;

生成器函数就就是这么运行的。

4.生成器相关操作:

1.X.__ next__()方法和next()内置函数

当我们调用一个生成器函数时来生成一个生成器X时,这个生成器对象就会自带一个X.__ next__()方法,它可以开始或继续函数并运行到下一个yield结果的返回或引发一个StopIteration异常(这个异常是在运行到了函数末尾或着遇到了return语句的时候引起)。也可以通过python的内置函数next()来调用X.__ next__()方法,结果都是一样的;

2.生成器函数协议中的send()方法

在讲send()方法的时候,有必要了解一下next()或__next__()或send()语句执行时,生成器内的程序执行到了哪里暂停了。写一个很简单的函数,使用pdb调试一下:

在第7行设置一个断点

通过看上面的程序,我们知道,当next()或__next__()或send()语句执行时,在生成器里面的程序中它执行到 yiled value 这条语句, 它yield出来了一个value值,但是没有执行yiled value表达式 的返回值它就暂停了;

现在说说send()方法:从技术上讲,yield是一个表达式,它是有返回值的,当我们使用内置的next()函数或__next__方法时,默认yield表达式的返回值为 None,它使用send(value)方法时,它可以把一个值传递给生成器,使得yield表达式的返回值为send()方法传入的值; 当我们第一次执行send()方法时,我们必须传入None值,因为第一次执行时,还没有等待返回值的yield表达式(虽然 send()方法会执行下一条yield语句,但是上面已经说明了它在还没有来得及执行yiled value表达式 的返回值时它就暂停了)

定义一个gen.py文件,里面的内容为:

3.生成器函数中的return 语句:

当生成器运行到了return语句时,会抛出StopIteration的异常,异常的值就是return的值; 另外,即使return后面有yield语句,也不会被执行;

4.另外,一个生成器对象也有close方法与throw方法,可以使用它们提前关闭一个生成器或抛出一个异常;使用close方法时,它本质上是在生成器内部产生了一个终止迭代的GeneratorExit的异常;

5. 最后一个要讲的内容:yield from

这个是在python3.0以后新增加的内容,可以让生成器delegate另一个生成器;

1.举一个例子看看它是怎么往外 yield数据的???

这个例子我们明白了两点:1. 当我们调用主生成器caller时,遇到yield from 时,它就会停下来,运行子生成器的程序, yield出来的数据就是子生成器里的数据;2. yield from 表达式的返回值为子生成器的return的值;

2.举个例子看看它是怎么通过 send()方法往里传递数据的?

通过这个例子,我们明白了1点:当主生成器遇到yield from以后,我们通过 send()方法传入值最终传给了子生成器;

3.通过 yield from ,可以嵌套调用生成器,比如:

转自:python中的生成器函数是如何工作的? - 殷大侠 - 侵删

jsp value设置为函数的返回值_python中的生成器函数是如何工作的?相关推荐

  1. java 函数参数 返回值_java中如何用函数返回值作为post提交的参数?

    1.我想实现的功能是在java程序中导入HttpURLConnection类,然后将函数的值作为post方法要提交的参数,最后显示在显示台上. 2.要用到的函数是自己写的可以显示实时计算机cpu.内存 ...

  2. keil5函数 默认返回值_Python中如何调用random()函数

    在开始了解之前,我们需要知道random()函数是需要导入模板,才可以进行访问,然后通过调用静态对象来使用这个方法,另外返回生成的随机实数,是有一定的范围.下面正式开始主题介绍: 先给大家带来一列实例 ...

  3. linux select函数返回值,socket中的select函数使用

    socket select()函数用于定时检查以创建的socket句柄的状态,以确定设定的socket句柄当前是否可写或有数据可读. select函数提供了一种方法,使得程序在操作socket时(如r ...

  4. ajax回调函数的返回值,使用ajax和回调函数向函数传递/返回值

    我试图读p_info函数返回从函数getproductInfo包含ajax调用,但我得到未定义的值.我使用回调函数来实现这一点,但仍然无法正常工作.我错在哪里?使用ajax和回调函数向函数传递/返回值 ...

  5. python函数返回值_Python中函数的返回值示例浅析

    前言: 前面我们介绍了简单的介绍了函数和函数的参数,今天我们来说一下Python中函数的返回值. 函数的返回值:函数运算的结果,需要进一步的操作时,给一个返回值return用来返回函数的结果,如果没有 ...

  6. python sort函数返回值_python中 sort方法 和sorted函数

    sort和sorted在python中常用语列表(或类列表)的排序,但是在python中有所区别. 他们的唯一的共同点恐怕就是都可以对列表排序,区别: 1. sorted是python的内置函数,可以 ...

  7. python怎么调用函数的返回值_python函数的返回值是什么

    返回值简介 函数需要先定义后调用,函数体中 return 语句的结果就是返回值.如果一个函数没有 reutrn 语句,其实它有一个隐含的 return 语句,返回值是 None,类型也是 'NoneT ...

  8. python函数默认返回值_python笔记20_函数返回值

    主要内容: 小目标:掌握函数返回值 主要内容:return语句,返回多个参数 如果看完这篇文章,你还是弄不明白函数返回值: 你来找我,我保证不打你,我给你发100的大红包. 1. 函数默认返回值 Py ...

  9. python定义函数后怎么输出_python中如何定义函数返回值

    返回值简介: 简单介绍print和return的区别,print仅仅是打印在控制台,而return则是将return后面的部分作为返回值作为函数的输出,可以用变量接走,继续使用该返回值做其它事. 函数 ...

最新文章

  1. windows串口控制linux,linux及windows下串口的使用.doc
  2. 【CVPR2020】30篇最新论文抢先看!!!
  3. linux系统运行状态检查
  4. 朴素贝叶斯Naïve Bayes分类算法在Hadoop上的实现
  5. Python的逻辑操作
  6. 《互联网时代》第五集 崛起
  7. java控制小数位数_java中怎么控制double的小数位数?
  8. Unity3d 场景搭建 基础 学习
  9. 高铁的速度 华为的服务
  10. Python 调用WebService接口出错-suds.transport.TransportError: HTTP Error 401: Unauthori
  11. 【科研工具】【MikTex】MikTex安装和使用
  12. 前端基础 HTML 第九章 使用框架结构 ----暑假学习第五天
  13. MOV AX,BX和MOV AX,[BX]的区别
  14. 数据处理之seaborn的学习
  15. 接口测试系列之 —— 前端交互测试和后端逻辑测试
  16. JZOJ【入门】1290 行李托运费
  17. Contiki开发1:Contiki与8位MCU
  18. windows cmd cd进入目录无效
  19. Powerdesigner使用手冊
  20. Nirvana NA公链 NAC公链的两面观

热门文章

  1. 深入理解BFC和Margin Collapse
  2. 关于在CVS下无法获取更新的解决方法!!!
  3. 砂.随笔.九.12.14公司停电,冒雨修爪爪
  4. Maven环境搭建(包括dependencies进度条不动解决方案)
  5. TIME_WAIT太多解决思路和方法
  6. android studio 使用问题 解决方法
  7. DeepFaceLab报错,CUDA driver is insufficient 解决方法!
  8. 根据接口文档中的入参,生成自动化测试用例中的异常测试用例,包含用例描述,用例数据
  9. 微信支付id出现的重复支付解决方法和app应用中多种支付方式之间的对比
  10. 论文|Airbnb Embedding的实践和思考