前言
上节记录了一些函数的基础,如函数的参数,函数的返回值,参数结构,函数的作用域等概念
这节说下函数的几个特性,比如闭包,应用传递,函数执行流程,生成器
下节课说下高阶函数和装饰器
闭包
很多无编程基础的小伙伴在刚学python时,说到闭包概念就开始晕(包括我),从而搞不懂后面的高阶函数,装饰圈等概念。
看看下面写的内容希望有帮助。
1 | #上一篇我们知道作用域的概念LEGB,下面我们来看个代码 |
小结
闭包:函数内部有函数,并且该函数调用上级函数变量,函数已经接受,但是函数部分变量引用还在这就是闭包。
引用传递
1 | def fn(x=[]): |
函数执行流程
函数执行过程,函数执行过程可视化地址。
在内存空间的划分:
1
2
3
4
5
6 > *堆 随机访问,用于保存数据,变量
> *栈 先进后出,用于保存现场
> *指令 顺序访问,用于存储程序指令
> *静态区
> *保留区
>
堆(heap),队列优先,先进先出(FIFO-First in First out)
栈(stack),先进后出(FILO-First-in/Last-out)
#先入后弹出,后入先弹出。类似弹夹,先放进去的最后出来,最后放进来的先出去
假设程序是单进程,单执行流,在某一时刻,能运行的程序只能有一个,但函数调用会打开新的执行上下文,因此为了确保main函数可以恢复现场
在main函数调用其他函数时,需要先把main现场保存下来,放一边,即栈中,这时候被调用的函数即可执行,且完成后可加到调用者,’回到’调用
者main,main可以继续向前运行.
1 | 执行流程: |
注:严格来说 引用真正的数据保存在堆里面,数据的引用地址保存在栈里面。
所有语言都是这么实现的
递归函数
1 | #什么是递归函数? |
####生成器
在介绍生成器前,需要介绍下生成式。
生成式
列表生成式
,字典生成式
,集合生成式
1 | #列表生成式 |
在字典,列表,集合中创建一个生成式,但是受内存的限制,容量肯定是有限的,比如一个包含100万个元素字典或者列表,只需要访问几个元素,这样不仅仅占用很大空间,而且绝大部分空间都浪费了。
生成器
在生成式中可以通过某种方式推算出来,那就可以在循环的过程中不断去推算出后续的元素,这样就不需要直接创建完整的元素,从而省去大量空间以及空间浪费等问题。
python中这一种循环的过程推算后续的元素 叫生成器
生成器的特性就是:惰性求值。
1 | #还是看刚才的例子,将列表[1,2,3,4,5]每个值*2 |
生成器函数
什么是生成器函数?
一个函数返回的是yield,name这个函数就是生成器函数
需要next调用
1 | #实例 |
迭代器
说到迭代器,大家可能会想到可迭代对象。
什么是可迭代对象?
1 | for i in [1,2,3,4,5]: |
总结
生成器都是迭代器,但是迭代器并不一定是生成器
生成器生成迭代器就是生成器本身。
通常我们叫迭代器也叫生成器。
生成器高级用法是用在协程上
协程: 是用户空间的轻量线程,跑在一个线程内,由用户空间调度
进程和线程是操作系统来调度
调度:由调度器来决定哪段代码来占用cpu时间)
内核态到用户态进行调度需要消耗时间跟资源,用户态跟用户态之间调度消耗资源小
协程也叫轻量线程非抢占式调度
生成器用法
1 | #生成器send()用法 |