Python高级之函数对象与闭包函数
1189 字
6 分钟
Python高级之函数对象与闭包函数
【一】函数对象
- 函数对象指的是函数可以被当做 数据 来处理,具体可以分为四个方面的使用
【1】函数可以被引用
# 定义一个函数def add(x, y): return x + y
# 将函数地址绑定给一个变量func = add# 通过这个变量找到对应的地址,从而调用函数res = func(1, 2)print(res) # 3【2】函数可以作为容器类型的元素
def add(x, y): return x + y
dic = {'add': add, 'max': max}print(dic) # {'add': <function add at 0x0000020523843E20>, 'max': <built-in function max>}res = dic['add'](1, 2)print(res) # 3【3】函数可以作为参数传入另外一个参数
def add(x, y): return x + y
def foo(x, y, func): return func(x, y)
res = foo(1, 2, add)print(res) # 3【4】函数的返回值可以是一个函数
def add(x, y): return x + y
def bar(): return add
func = bar()print(func) # <function add at 0x00000239EC363E20>res = func(1, 2)print(res) # 3【二】闭包函数
【1】什么是闭包
- 闭包是指包含对自由变量的函数和对这些变量的引用环境的组合。
- 基于函数对象的概念,可以将函数返回到任意位置去调用
- 但作用域的关系是在定义完函数时就已经被确定了的,与函数的调用位置无关。
# 定义全局变量x_global = 1
# 定义外层函数def outer(): def inner(): print(x_global)
return inner
def func(): x_func = 3 # 调用f1()返回函数f2 inner = outer() # 需要按照函数定义时的作用关系去执行,与调用位置无关 inner()
func() # 结果为1【2】什么是闭包函数
- 也就是说函数被当做数据处理时,始终以自带的作用域为准。
- 若内嵌函数包含对外部函数作用域(而非全局作用域)中变量的引用
- 那么该’内嵌函数’就是闭包函数,简称闭包(Closures)
# 定义全局变量x_global = 1
def outer(): # 定义局部变量,覆盖全局变量 x_global = 2
def inner(): # 打印外部函数的局部变量 print(x_global)
return inner
func = outer()func()# 结果为2【3】如何查看闭包函数所包裹的外部变量
- 可以通过函数的closure属性,查看到闭包函数所包裹的外部变量
# 定义全局变量x_global = 1
def outer(): # 定义局部变量,覆盖全局变量 x_global = 2
def inner(): # 打印外部函数的局部变量 print(x_global)
return inner
func = outer()func()# 结果为2
res_first = func.__closure__print(res_first) # (<cell at 0x000001945A08B9A0: int object at 0x0000019459AA0110>,)
print(dir(func.__closure__[0]))'''['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']'''
# __closure__ 属性是一个元组,包含了函数闭包中的每个 cell 对象。每个 cell 对象都有一个 cell_contents 属性,它存储着相应的值。res_second = func.__closure__[0].cell_contentsprint(res_second) # 2- “闭”代表函数是内部的,“包”代表函数外’包裹’着对外层作用域的引用。
- 因而无论在何处调用闭包函数,使用的仍然是包裹在其外层的变量。
【4】闭包函数用途
(1)保持状态
- 保持状态: 闭包可以用来保持函数调用之间的状态。
- 目前为止,我们得到了两种为函数体传值的方式
- 一种是直接将值以参数的形式传入
- 另外一种就是将值包给函数
[1]将值以参数的形式传入
import requests
# 将值以参数的形式传入def get(url): return requests.get(url).text[2]将值包给函数
import requests
# 将值包给函数def page(url): def get(): return requests.get(url).text
return get[3]对比
- 方式一在下载同一页面时需要重复传入url
- 方式二只需要传一次值,就会得到一个包含指定url的闭包函数,以后调用该闭包函数无需再传url
import requests
# 将值以参数的形式传入def get(url): return requests.get(url).text
# 方式一下载同一页面get('https://www.python.org')get('https://www.python.org')get('https://www.python.org')import requests
# 将值包给函数def page(url): def get(): return requests.get(url).text
return get
# 方式二下载同一页面python = page('https://www.python.org')python()python()python()(2)函数工厂
- 函数工厂: 闭包允许创建函数工厂,即可以动态生成函数。
- 在你的例子中,page 函数就是一个函数工厂,它返回一个根据传入的 url 动态生成的函数。
import requests
# 将值包给函数def page(url): def get(): return requests.get(url).text
return get
python = page('https://www.python.org')java = page('https://www.java.com')(3)封装
- 封装: 闭包可以用来实现类似面向对象编程中的封装概念。
- 通过将函数和其相关的状态(变量)捆绑在一起,形成一个封闭的单元。
def counter(): count = 0
def increment(): nonlocal count count += 1 return count
return increment
counter1 = counter()counter2 = counter()
print(counter1()) # 1print(counter1()) # 2print(counter2()) # 1支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!
相关文章智能推荐
1
C 语言变量与存储类型
编程语言理解 C 语言变量的定义、命名规则、作用域,以及 auto、register、extern 和 static 存储类型。
2
C 语言关系与逻辑运算符
编程语言学习 C 语言的关系运算符、逻辑运算符、短路求值和条件判断规则。
3
C 语言开发环境的安装与配置
编程语言在 Windows、Linux 与 macOS 上安装 C 工具链,配置编辑器,并编译运行第一个 C 程序。
4
C 语言初识:程序运行机制与基本结构
编程语言认识 C 程序从源代码到运行的完整流程,以及基础语法和程序的基本结构。
5
C 语言基础:注释、关键字、变量与数据类型
编程语言学习 C 语言的注释、关键字、标识符、常量、变量和基本数据类型等基础知识。
随机文章随机推荐














