Day06 -函数
1.基础
1.1为何用函数
- 组织结构不清晰,可读性差
- 代码冗余
- 可维护性、扩展性差
1.2如何用函数
1)先定义
#3种定义
#基本:
def 函数名(self1,self2):
'''
文档描述(推荐写)
'''
函数体
return 值
#方法一(无参函数):
def func():
pass
func()
#方法二(有参函数):
def func2(x,y):
pass
func2(x,y)
#方法三(空函数,函数体代码为pass):
def func3():
pass
1.2.1定义函数发生的事情
- 申请内存空间保存函数体代码
- 将上述内存空间绑定给函数名
- 定义函数阶段不会执行函数体代码,但会检测函数体语法
1.2.2 应用场景
#无参函数应用场景
#有参函数应用场景
#空函数应用场景--构思的时候
2)后调用
#语句的形式 只调用函数
#表达式形式 拿到返回值
#函数调用可以当做参数
调用函数发生的事情
- 通过函数名找到函数的内存地址
- 加括号触发函数体代码的执行
3)返回值
#返回值三种形式
#return功能
'''
1.是结束的标志,运行到return会立刻终止,并且当return后的值会当做本次运行的结果返回
2.
'''
#返回None:函数体内没有return/或return/return None
#返回一个值:return 10
#返回多个值:return 10,'aa',[1,2]#用逗号分割,返回成元组类型
2.形参与实参
形参:在定义函数阶段定义的参数称之为形式参数,简称形参#相当于变量名
实参:在调用函数阶段传入的值称之为实际参数,简称实参#相当于变量值
关系:在调用阶段,实参会赋值(内存地址绑定)给形参。绑定关系只能用于函数体
#实参与形参绑定关系在调用时生效,在调用结束后解除绑定
2.1实参的形式
- 直接的值
- 变量
- 只要结果是值就可以
2.2位置参数(两种)
按照从左到右顺序依次定义的参数,特点***必须被传值***
2.3 关键字参数(实参)
关键字实参:在调用阶段按照key=value的形式传值,特点:可以给某个形参传值,完全不参照顺序
关键字实参和位置实参混合使用时
- 位置实参必须放在关键字实参之前
- 不能为同一个形参重复传值
2.4默认形参
定义函数阶段,就已经被赋值的参数叫做默认参数,意味着在调用阶段可以不用为其赋值
位置形参与默认形参混合使用时
- 位置形参必须在默认形参左边
- 默认参数的值是在定义阶段被赋值的(,被赋予的是内存地址,可变类型依旧可变)
- 虽然默认值可以被指定为任意数据类型,不推荐使用可变类型
2.5可变长参数
可变长度指的是在调用函数时,传入的值(实参)的个数不固定
所对应的是接收的形参也应该是不固定的
2.5.1 用来接收溢出的位置实参
#*形参名:溢出的实参会被*保存成元组的格式,然后赋值给紧随其后的形参名
#规范:'*args'
2.5.2 用来接收溢出的关键字实参
#**形参名:用来接收溢出的关键字实参,保存成字典形式
#规范:**kwargs
2.5.3 实参
实参中带’*'会将后面的打散,然后按照位置传参
实参中带’**’(后面只能跟字典)会将后面的打散,然后按照关键字传参
2.5.4 形参与实参都带’ * '/ ‘**’
先解决实参在赋值形参
#混合*与**
#*args必须在**kwargs之前
2.6 命名关键字参数
在定义函数时*后定义的参数,称之为命名关键字参数
def func(x,y,*,a,b):#a,b称为命名关键字参数
pass
#特点1:命名关键字参数必须按照关键字实参的形式传参
#特点2:在定义阶段时可以为命名关键字参数赋值
2.7组合使用
#形参顺序:位置形参,默认形参,*args,命名关键字参数,**kwargs
#实参顺序:位置实参,关键字实参
3.名称空间
用来存放名字的地方,是对栈区的划分
3.1内置名称空间
-
存放的名字:python解释器内置的名字
-
存活周期:python解释器启动即产生,python解释器关闭即销毁
3.2全局名称空间
-
存放的名字:运行顶级代码所产生的名字(不是函数内定义的,也不是内置的)
-
存活周期:运行程序时产生,结束时销毁
3.3局部名称空间
-
存放的名字:调用函数时,运行函数体代码过程中产生的函数内的名字
-
存活周期:调用函数时存活,函数调用结束后销毁
3.4加载顺序
内置名称空间>全局名称空间>局部名称空间
3.5销毁顺序
局部名称空间>全局名称空间>内置名称空间
3.6名字查找的优先级
-
当前所在位置向上一层一层查找
-
名称空间的’嵌套关系’是以函数定义阶段为准的与调用位置无关
-
函数嵌套定义
4.全局作用域和局部作用域
4.1全局作用域:内置名称空间、全局名称空间
- 全局存活
- 全局有效:被所有函数共享
4.2局部作用域:局部名称空间的名字
- 临时存活
- 局部有效:只在函数体内有效
5. Global与nonlocal
Global:不可变类型:在函数体内使用时声明global;可变类型不需要声明
nonlocal:修改函数外层函数的值所对应的值(不可变类型)
6.闭包函数
闭包函数=名称空间与作用域+函数嵌套+函数对象
核心点:名字查找关系是以函数定义阶段为准
6.1什么是闭包函数
#闭:该函数是内嵌函数
#包:该函数包含对外层函数(不是全局)作用域名字的应用
6.2 闭包函数的场景
需要不改变模块源码的情况下为模块添加新功能