1.函数对象
(对象存储数据的盒子)
通用的含义和功能:
可以赋值给变量
可以作为函数的参数
可以作为函数的返回值
与别的对象关联,并作为其中的一部分
1.1对象的通用属性
# id 数据类型 值
def aa():
print('123')
print(id(aa)) # id 16216560
print(type(aa)) # <class 'function'>
print(aa) # <function aa at 0x0000000000F47310>
1.2函数赋值给变量
def aa():
print('123')
f = aa # 内存地址---> f
f() # 内存地址 + () 执行函数体
1.3函数作为参数
def bb():
print('from bb()')
def aa(x):
x()
aa(bb) # from bb()
1.4函数作为返回值
def bb():
print('from bb()')
def aa(x):
return x
# 将bb函数的内存地址给x 然后返回x 赋值给 y
y = aa(bb)
y() # 内存地址 + () --显示--> from bb()
1.5函数当作容器类型的元素
def aa():
print('退出')
def bb():
print('进入')
list_1 = {'0': ['退出', aa], '1': ['进入', bb]}
while True:
# 功能显示
for i in list_1: # 遍历字典的键值 '0' '1'
print(i, list_1[i][0]) # 字典键名 和第一个值
# 功能选择
xu = input('请选择:')
if xu in list_1: # 判断输入的选项 是否 在字典内
list_1[xu][1]() # 第二个值是函数名 加上括号 执行
else:
print('输入不正确')
2.函数嵌套
函数嵌套的调用:在调用一个函数的过程中,该函数内部调用其他函数
函数的嵌套定义:在函数内定义其他函数
# 嵌套使用
def max2(x, y): # 两个值比较,反正较大的值
if x > y:
return x
else:
return y
def max4(a,b,c,d):
res1 = max2(a, b)
res2 = max2(res1, c)
res3 = max2(res2, d) # 第三次比较为最终结果
print(res3)
max4(123, 456, 789, 147) # 传入值
# 函数自己调用自己
def aa(x):
x += 1
print(x) # 第997次报错
aa(x)
aa(0)
# RecursionError: maximum recursion depth exceeded while calling a Python object
3.嵌套定义
from math import pi # 导入模块
def aa(x, mode=0): # 传入参数,(半径, 返回值选择)
def b(x):
return x * pi * 2 # 圆的周长
def c(x):
return pi * (x ** 2) # 圆的面积
if mode == 0: # 判断模式
return b(x)
else:
return c(x)
res = aa(30, mode=1)
print(res)
4.名称空间与作用域
名称空间:存放名称(变量名,函数名)与内存地址绑定关系
内置名称空间:python自带的名称 生命周期:解释器启动则产生,解释器关闭则销毁
全局名称空间:顶级名称(全局名称) 生命周期:运行python文件则立即产生,文件运行完毕则销毁
局部名称空间:函数内内的名称 生命周期:调用函数则产生,函数调用完毕则销毁
名称空间划分三个,每个空间中可以出现相同的名称
***名称查找优先级:局部->全局->内置 (基于当前位置向外查找 LEGB)
***名称空间的嵌套关系是以函数定义为准生成的与调用位置无关
内置 --> b 空间
全局 --> g 空间
局部 --> e 空间
局内局 --> l 当前所有局部空间
4.1名称查找优先级
局部->全局->内置 (基于当前位置向外查找 LEGB)
len = 10
def aa():
len = 100
print(len) # 1.首先在当前作用域查找 len , len存在
aa() # 2. 显示 100
len = 10 # 向外在全局查找 找到 len
def aa():
print(len) # 1.首先在当前作用域查找 len , len不存在
aa() # 3. 显示 10
# 3. 再向外在内置查找 len存在,len是内置的一个函数
# 2. 向外在全局查找 len不存在
def aa():
print(len) # 1.首先在当前作用域查找 len , len不存在
aa() # 4. 显示 len函数的内存地址 <built-in function len>
x = 0
def aa():
print(x) # 首先在当前作用域查找 len , len存在,就不会去其他位置找,但是,赋值之前引用就会报错
x = 111
aa() # UnboundLocalError: local variable 'x' referenced before assignment 局部变量'x'在赋值之前引用
4.2名称空间关系
名称空间的嵌套关系是以函数定义为准生成的与调用位置无关
x = 0 # 2. 在全局名称空间站找到了 x = 0
def aa():
print(x) # 1. 在定义阶段 局部名称空间找不到x 往上在全局名称空找
def bb():
x = 1
aa() # 函数aa在全局名称空间中创建,不是在函数bb的局部名称空间创建,他们不在同一个名称空间中。
bb() # 0
def aa():
print(x) # 1. 在定义阶段 局部名称空间找不到x 往上在全局名称空找
x = 1 # 2. 在全局名称空间找到了 x = 1 的新值
# 3. 在调用时,全局名称空间内已经只有有就可以
def bb():
x = 2 # 改成2
aa()
bb() # 1
5.全局作用域 与局部作用域
全局作用域:全局存活,全局有效(内置名称空间,全局名称空间)
局部作用域:临时存活,局部有效(局部名称空间)
5.1 global 关键字
设置全局变量
x =1 # 不可变类型
def aa():
global x # 将x 作用于全局名称空间
x = 10
aa()
print(x) # 10
list_1 = [1, 2, 3] # 可变类型
def aa():
list_1.append(4) # 就地修改了值
aa()
print(list_1)
5.2 nonlocal关键字
声明一个名称是来自外层函数,没有外层函数,不会找到全局名称作用域去,会报错
x =1
def aa():
x = 10
def bb():
nonlocal x # 作用于函数内的上一层,上一层为全局则报错
x = 20
bb()
print(x)
aa()
print(x)
6.闭包函数
闭包函数 = 函数对象 + 函数嵌套定义+ 名称空间与作用域
闭函数:定义在函数内部的函数
作用:闭包函数是一种为函数体传参的方案
包函数:内部函数引用了一个外层函数的名称
6.1函数体传参方案一:直接使用形参
def dog(bun):
print(bun)
dog('肉包子')
dog('菜包子')
6.2函数体传参方案二:闭包函数
# 需要使用这个函数,又不能写入参数时使用闭包函数
def sack(bun):
def dog():
print(bun)
return dog
dog = sack('肉包子')
dog()