一、函数
函数是实现特定功能的代码段的封装,在需要时可以多次调用函数来实现该功能。
python如下定义一个函数,我们可以通过任何变量来将此函数进行赋值操作,如下:
def greet(): return "hello!" # 将方法赋给变量(无括号,得到方法对象) greet_func = greet # 调用存储在变量中的方法 print(greet_func()) print(type(greet_func)) # 输出 greet_func 的类型,由于 greet_func 指向的是 greet 函数对象,所以输出结果为 <class 'function'> print(type(greet_func())) # 先调用 greet_func 所指向的函数,得到返回值 "hello!",然后输出该返回值的类型,结果为 <class 'str'>。 # 有括号,直接调用方法并将结果赋给变量 greet_result = greet() print(greet_result) print(type(greet_result)) # 输出 greet_result 的类型,由于它存储的是字符串,所以输出结果为 <class 'str'> print(type(greet_result())) # 报错greet_result 存储的是字符串 "hello!",而不是函数对象,所以不能像调用函数一样在它后面加上括号 ()
在 python 中,函数是一等公民,这意味着函数可以像其他对象(如整数、字符串等)一样被赋值给变量。这里将 greet
函数对象赋值给了变量 greet_func
。此时 greet_func
实际上指向的是 greet
函数本身,而不是函数的返回值;而 greet_result = greet()
是先调用 greet
方法,然后把返回值赋给 greet_result
变量。
二、闭包
2.1 概念
在 python 中,闭包(closure)是一种特殊的函数,它由一个函数和该函数所引用的外部作用域中的变量组成。即使外部函数已经执行完毕,其局部变量的生命周期也会因闭包的存在而得以延长,闭包可以继续访问这些变量。
简单来说,闭包允许函数访问并操作其定义所在的外部作用域中的变量,即使该外部作用域已经结束。
构成闭包需要满足以下三个条件:
- 存在一个嵌套函数,即在一个函数内部定义另一个函数。
- 嵌套函数引用了外部函数的局部变量。
- 外部函数返回嵌套函数。
2.2 闭包的应用场景
- 数据封装和隐藏:可以将数据隐藏在闭包内部,只通过闭包提供的接口来访问和修改数据。
- 实现回调函数:在事件驱动编程中,闭包可以作为回调函数,保存一些上下文信息。
- 实现装饰器:装饰器是闭包的一种常见应用,用于在不修改原函数代码的情况下,为函数添加额外的功能。
2.3 代码实例
实例 1:简单计数器闭包
def outer_function(): # 外部函数的局部变量 count = 0 def inner_function(): # 声明count为外部函数的局部变量, 以便可以修改它 nonlocal count count = count + 1 return count return inner_function # 创建闭包实例 counter = outer_function() # 多次调用闭包 print(counter()) # 输出: 1 print(counter()) # 输出: 2 print(counter()) # 输出: 3
代码解释:
outer_function
是外部函数,它定义了局部变量count
并初始化为 0。inner_function
是嵌套在outer_function
内部的函数,它引用了外部函数的count
变量,并对其进行加 1 操作。nonlocal
关键字用于告诉 python,count
变量不是当前inner_function
的局部变量,而是外部函数的局部变量,这样才能在内部函数中修改它。outer_function
返回了inner_function
,形成了闭包。当调用outer_function()
时,会返回inner_function
的引用并赋值给counter
。每次调用counter()
时,count
变量的值都会在之前的基础上增加 1,说明count
变量的状态被闭包保存下来了。
实例 2:带参数的闭包
def multiplier(factor): print("++++++", factor) def multiply_by_factor(number): print("++++++", number) return number * factor return multiply_by_factor # 创建一个乘以 3 的闭包 triple = multiplier(3) # 调用 __closure__ 内置方法可以查看到两个内存地址,结果返回cell就是闭包,none 则不是闭包,可以看出来其实这是一个元组类型,使用[0].cell_contents可以得到闭合数值,也就闭包所需要的环境变量。 print(triple.__closure__) # 闭包所需要的环境变量 print(triple.__closure__[0].cell_contents) print(triple.__class__) print(triple(5))
代码解释:
multiplier
是外部函数,它接受一个参数factor
。multiply_by_factor
是嵌套函数,它接受一个参数number
,并返回number
乘以factor
的结果。multiplier
返回multiply_by_factor
,形成闭包。调用multiplier(2)
会返回一个闭包,该闭包会将传入的数字乘以 2,将其赋值给double
。同理,multiplier(3)
返回的闭包会将传入的数字乘以 3,赋值给triple
。
运行结果:
实例 3:闭包用于数据封装和隐藏
def account(initial_balance): balance = initial_balance def deposit(amount): nonlocal balance balance = balance + amount return balance def withdraw(amount): nonlocal balance if amount <= balance: balance = balance - amount return balance else: print("余额不足") return balance def get_balance(): return balance return deposit, withdraw, get_balance # 创建账户闭包 deposited, withdrawed, get_balanceed = account(1000) # 存款操作 print(deposited(500)) # 输出: 1500 # 取款操作 print(withdrawed(200)) # 输出: 1300 # 查询余额 print(get_balanceed()) # 输出: 1300
代码解释:
account
是外部函数,它接受一个初始余额initial_balance
并将其赋值给局部变量balance
。deposit
、withdraw
和get_balance
是嵌套函数, 它们 都引用了外 部函数balance
变量。deposit
函数用于存款,withdraw
函数用于取款,get_balance
函数用于查询余额。account
函数返回这三个嵌套函数,形成闭包。通过调用account(1000)
创建了一个账户闭包,并将返回的三个函数分别赋值给deposited
、withdrawe
和get_balanceed
。可以通过调用这些函数来进行账户的存款、取款和查询余额操作, 而balance
变量被封装在闭包内部,外部无法直接访问,实现了数据的封装和隐藏。
参考文章:
https://zhuanlan.zhihu.com/p/55949749
到此这篇关于python函数闭包概念的文章就介绍到这了,更多相关python函数闭包内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论