函数对象和闭包
-
函数对象指的是函数可以被当做数据来处理, 分为四种
# func=内存地址
def func():
print('from func')
# 可以赋值
# f = func
# print(f, func)
# f()
1.2 可以当做函数参数传给另外一个参数
def func():
print('from func')
def foo(x): # x=func的内存地址
print(x)
func()
foo(func) # foo(func的内存地址)
1.3 可以当作函数的返回值
def func():
print('from func')
def foo(x): # x=func的内存地址
return x # return func的内存地址
res = foo(func) # foo(func的内存地址)
print(res) # res=func的内存地址
1.4 函数可以当作容器类型的元素
def func():
print('from func')
l = [func,]
print(l)
l[0]()
dict1 = {'k1':func}
print(dict1)
dict1['k1']()
1.5 函数对象应用的例子
# 函数对象应用的示例
def login():
print('登陆功能')
def register():
print('注册功能')
def transfer():
print('转账功能')
func_dict = {
'0': ['退出', None],
'1': ['登陆', login],
'2': ['注册', register],
'3': ['转账', transfer]
}
while True:
for key, value in func_dict.items():
# 循环显示func_dict内容
print(key, value[0])
choice = input('请输入命令: ').strip()
if not choice.isdigit():
print('必须输入数字: ')
continue
if choice == '0':
break
if choice in func_dict:
func_dict[choice][1]()
else:
print('输入命名不存在: ')
二 闭包
-
闭包只能存在嵌套函数中
-
内层函数对外层函数非全局变量的引用(使用), 就会形成闭包
-
闭包函数=名称空间与作用域+函数嵌套+函数对象
-
核心: 名字的查找关系是以函数定义阶段为准
# 简单闭包函数
def f1():
x = 222222
def f2():
print(x)
f2()
x = 11111
f1() # 结果是222222,
# 封闭的东西: 保证数据的安全
# 方案一
l1 = [] # 全局变量 数据不安全
li = []
def make_average(new_value):
l1.append(new_value)
total = sum(l1)
averager = total/len(l1)
return averager
print(make_average(1000))
print(make_average(2000))
print(make_average(3000))
# 闭包
def make_average():
l1 = []
def averager(nwe_value):
l1.append(nwe_value)
total = sum(l1)
return total/len(l1)
return averager
avg = make_average()
print(avg(20000))
print(avg(30000))
print(avg(10000))
-
被引用的非全局变量也称自由变量, 这个自由变量会与内层函数产生一个绑定关系
-
自由变量不会在内存中消失
-
闭包的作用: 保证数据的安全
2.1 判断函数是否是闭包函数
def make_averager():
series = []
def averager(new_value):
series.append(new_value)
total = sum(series)
return total/len(series)
return averager
avg = make_averager()
# 函数名.__code__.co_freevars 查看函数的自由变量
print(avg.__code__.co_freevars) # ('series',)
# 函数名.__code__.co_freevars 查看函数的自由变量
print(avg.__code__.co_freevars) # ('series',)
# 函数名.__code__.co_varnames 查看函数的局部变量
print(avg.__code__.co_varnames) # ('new_value', 'total')
# 函数名.__closure__ 获取具体的自由变量对象,也就是cell对象。
# (<cell at 0x0000020070CB7618: int object at 0x000000005CA08090>,)
# cell_contents 自由变量具体的值
print(avg.__closure__[0].cell_contents) # []
2.3 闭包的使用
-
两种函数传参的方式
# 方式一: 直接把函数体需要的参数定义成形参
def func1(x):
print(x)
func1(2)
# 方式二:
def func1(x):
x = 3
def func2():
print(x)
return func2
x = func1(3)
print(x)
-
示例
# 传参的方案一, 下载同一个页面
def get(url):
response = requests.get(url)
print(response.text)
get('https://www.baidu.com')
get('https://www.baidu.com')
# 传参的方案二: 下载同一个页面
import requests
def out(url):
def get():
response = requests.get(url)
print(len(response.text))
return get
result = out('https://www.baidu.com')
result()
result()# 可以在多处调用