python基础 —— 闭包 closure 与 装饰器

本文详细解析了Python中的闭包概念,包括数据封装、内部函数引用外部变量的作用域特性,以及如何利用闭包实现函数式编程中的数据私有化。同时,深入探讨了装饰器的使用,讲解了如何在不修改原函数的基础上增加新功能,以及如何使用带参数的装饰器和静态方法、类方法装饰器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:https://www.bilibili.com/video/av18586448?from=search&seid=6082666377841139699

闭包:数据封装

内部函数对外部函数作用域里变量的引用
在函数式语言中,当内嵌函数体内引用到体外的变量时,将会把定义时涉及到的引用环境和函数体打包成一个整体(闭包)返回。

  1. 内部函数在外部函数执行过程中创建
    内部函数在未创建前,不能直接调用
def func():  # 外部函数
	print("this is func.")
	def func1():  # 内部函数
		print("this is func1.")

# func1()  # error

func1创建过程在func函数的执行过程中

  1. 外部函数执行期间,创建了内部函数,但外部函数执行结束时,创建的变量被回收
# func()  # 函数内部创建了func1
# func1() # error

函数内部创建了func1,但函数内变量生命周期仅在函数执行期间

  1. 外部函数,返回:内部函数对象
def func2():
	a = 1  # 外部函数作用域里的变量,当使用了del var时,a回收
	print("this is func2")
	def fun3(num):  # 数据封装:闭包内的闭包函数私有化了变量,如a
		print("this is func3")
		print(num + a)  # 引用外层函数中的局部变量a
	return fun3

var = func2()
var(3)  # 执行了func3,执行完成后被回收
# print(a)  # del var时被回收

调用外部函数后赋值给变量var,保留了内部函数对象

  1. 每次调用外部函数 时都 返回一个新的闭包(引用环境和函数体)实例
def exFunc(n):
	sum = n
	def inFunc():
		return sum + 1
	return inFunc()

myFunc1 = exFunc(10)  # 当内嵌函数体内引用到体外的变量时,将会把定义时涉及到的引用环境和函数体打包成一个整体(闭包)返回
myFunc1()

# 每次调用exFunc函数 时都将返回一个新的闭包实例
# 这些实例之间是隔离的,分别包含调用时不同的引用环境现场。
myFunc2 = exFunc(20)  # 每次调用外层函数后都将生成并保存一个新的局部变量
myFunc2()
mylist = [1,2,3,4,5]
def func4(obj):
	print("func4:" , obj)
	def func5():
		obj[0] += 1
		print('func5:', obj)
	return func5
var = func4(mylist)
var()
var()
var()

output:
func4: [1, 2, 3, 4, 5]
func5: [2, 2, 3, 4, 5]
func5: [3, 2, 3, 4, 5]
func5: [4, 2, 3, 4, 5]

装饰器

不影响原有函数功能,并添加新功能

1.

def func1(func):  # 必须有参数,接收被装饰的函数对象
	def func2():
		print("this is func2")
		return func  # 返回外部函数接收的被装饰函数的调用
	return fun2

# return func  # 返回函数对象
# return func()  # 返回函数调用

# @func1:先执行func1,myprint作为参数传入
# @func1相当于func1(myprint)():①func1(myprint) -> func2 ②func2() -> return func().
@func1
def myprint():
	print("this is myprint")

myprint()  # func1(myprint)()

2. 带参数

def arg_func(sex):
	def func3(b_func):
		def func4():
			if sex == 'man':
				print("不可以生娃")
			if sex == 'woman':
				print("可以生娃")
			return b_func()
		return func4
	return func3


# arg_func(sex) -> func3
# func3(b_func) -> func4
# func4() -> return b_func()
@arg_func(sex='man')  # 带参数传入
def man():
	print("好好工作")

@arg_func(sex='woman')
def woman():
	print("好好工作")

man()
woman()

静态方法装饰器 @staticmethod

staticmethod()返回函数的静态方法

class C(Object):
	@staticmethod
	def f(arg1, arg2, ...):
		...

# 可以不用实例化,通过C.f()调用
C.f()
# 可实例化后调用C().f()
cobj = C()
cobj.f()

类方法装饰器@classmethod

在当前函数内要访问当前类的属性或函数,需要通过在函数参数中定义一个参数来传递当前类对象,参数名自定,如参数.属性或参数.方法()。
如果是其他类或包需要调用当前函数,可以通过类方法和实例方法来调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值