返回顶部

函数对象和闭包

一 函数对象

  • 函数对象指的是函数可以被当做数据来处理, 分为四种

1.1 可以把函数当作变量

# 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()# 可以在多处调用
posted @ 2022-07-21 20:32  fuju  阅读(42)  评论(0)    收藏  举报