递归函数***
函数执行流程
函数的活动和栈有关。
栈是后进先出的数据结构。
栈是从底向顶端生长,栈中插入数据称为压栈、入栈,从栈顶弹出数据称为出栈。
C语言中,每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。
函数的每一次调用都会创建一个独立的栈帧(Stack Frame)入栈。
因此,可以得到这样一句不准确的话:哪怕是同一个函数两次调用,每一次调用都是独立的,这两次调用没什么关系。
生成器***
生成器generator
- 生成器指的是生成器对象,可以由生成器表达式得到,也可以使用yield关键字编写一个生成器函数,调用这个函数得到一个生成器对象
- 生成器对象,是一个可迭代对象,是一个特殊的迭代器
- 生成器对象,是延迟计算、惰性求值的
生成器函数
- 函数体中包含yield语句的函数,就是生成器,调用后返回生成器对象(每次调用都会生成一个不同的生成器)
- 普通函数调用函数会立即执行知道执行完毕;生成器函数调用,并不会立即执行函数体,而是返回一个生成器对象,需要使用next函数或for循环来驱动这个生成器对象。
- 生成器表达式和生成器对象都能生成生成器对象。只不过生成器函数可以写更加复杂的逻辑
生成器函数的执行
- 在生成器函数中,可以使用多次yield,每执行一次yield后会暂停执行,把yield表达式的值返回
- 再次执行会执行到下一个yield语句又会暂停
- 函数返回
- return语句依然可以终止函数运行,但return语句的返回值不能被获取到
- return会导致当前函数返回,无法继续执行,也无法继续获取下一个值,抛出StopIteration异常
- 如果函数没有显示的return语句,如果生成器函数执行到结尾(相当于执行了return None),一样会抛出StopIteration异常
yield form语法
从Python3.3开始增加了yield from语法,使得
yield from iterable
等价于for item in iterable:yield item
yield from就是一种简化语法的语法糖。
本质上,yield from的意思,就是从from后面的可迭代对象中拿元素一个个yield出去。
生成器应用
生成器的核心就是按需计算,需要的时候运行,不需要的时候暂停,而且每次运行都是针对同一个对象。而函数调用不是,函数的每次调用都是重新构建。
1、无限循环
2、计数器
3、斐波那契数列
4、生成器交互
Python提供了一个和生成器对象交互的方法send,该方法可以和生成器沟通
- 调用send方法,就可以把send的实参传给yield语句做结果,这个结果可以在等式右边被赋值给其他变量。(不赋值则返回值被丢弃,没有了意义)
- send和next一样可以推动生成器启动并执行
5、协程Coroutine
- 生成器的高级用法
- 它比进程、线程轻量级,是在用户空间调度函数的一种实现
- Python3 asynicio就是协程实现,已经加入标准库
- Python3.5 使用async、await关键字直接原生支持协程
- 协调调度器实现思路:
- 有2个生成器A、B,next(A)后,A执行到yield语句暂停,然后去执行next(B),B执行到yield语句也暂停,然后再次调用next(A),再调用next(B),周而复始,就实现了调度的效果。可以引入调度的策略来实现切换的方式
- 协程是一种非抢占式调度