参考:https://www.bilibili.com/video/av18586448?from=search&seid=6082666377841139699
闭包:数据封装
内部函数对外部函数作用域里变量的引用
在函数式语言中,当内嵌函数体内引用到体外的变量时,将会把定义时涉及到的引用环境和函数体打包成一个整体(闭包)返回。
- 内部函数在外部函数执行过程中创建
内部函数在未创建前,不能直接调用
def func(): # 外部函数
print("this is func.")
def func1(): # 内部函数
print("this is func1.")
# func1() # error
func1创建过程在func函数的执行过程中
- 外部函数执行期间,创建了内部函数,但外部函数执行结束时,创建的变量被回收
# func() # 函数内部创建了func1
# func1() # error
函数内部创建了func1,但函数内变量生命周期仅在函数执行期间
- 外部函数,返回:内部函数对象
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,保留了内部函数对象
- 每次调用外部函数 时都 返回一个新的闭包(引用环境和函数体)实例
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
在当前函数内要访问当前类的属性或函数,需要通过在函数参数中定义一个参数来传递当前类对象,参数名自定,如参数.属性或参数.方法()。
如果是其他类或包需要调用当前函数,可以通过类方法和实例方法来调用。