核心概念:
- 函数是第一类对象 (First-Class Objects): 在Python中,函数可以像普通变量一样被赋值、作为参数传递给另一个函数、从另一个函数返回。
- 闭包 (Closure): 当一个内部函数引用了外部函数作用域中的变量,即使外部函数已经执行完毕,这个内部函数(及其引用的外部变量)仍然存在。装饰器就是利用闭包来“记住”被装饰的函数。
- 装饰器 (Decorator) 是什么?
- 本质上是一个函数,它接收另一个函数(被装饰的函数)作为参数,并返回一个经过包装或修改后的新函数。
- 它的主要作用是在不修改原函数代码的情况下,动态地给函数增加额外的功能。
- 语法糖
@:@my_decorator放置在函数定义前,等价于my_function = my_decorator(my_function)。它使装饰器的使用更简洁直观。
闭包:
上述概念里其他还好,闭包的概念有点抽象。我们举个例子。
# 闭包
def add_out(x):
def add_in(y):
result = x+y
return result
return add_in
a = add_out(4)
print(a(5)) # 9
其实就是通过两个函数嵌套,调用外面函数时候将4这个值存进去。有点类似于类,下面这样来看就很清晰了,这儿大概知道有闭包功能。
class add_out():
def __init__(self,x):
self.x = x
def add_in(self, y):
result = self.x+y
return result
a = add_out(4)
print(a.add_in(5)) # 9
装饰器:
刚才看到Python闭包的能力,在考虑到之前说函数是第一类对象,也就是函数也能当个变量,所以……就可以进一步这样做,把函数先存起来,用的时候就顺手把日志功能加进去了:
def logger(func):
def wrapper(*args, **kwargs):
print(f"执行函数: {func.__name__}")
result = func(*args, **kwargs)
print(f"函数 {func.__name__} 执行完毕。")
return result
return wrapper
def say_hello(name):
print(f"你好, {name}!")
hello = logger(say_hello)
hello("张三")
# 执行函数: say_hello
# 你好, 张三!
# 函数 say_hello 执行完毕。
不过这样不太好看,而且怎么看怎么有点绕,于是就有了@那个装饰器符号,看起来舒服多了。
def logger(func):
def wrapper(*args, **kwargs):
print(f"执行函数: {func.__name__}")
result = func(*args, **kwargs)
print(f"函数 {func.__name__} 执行完毕。")
return result
return wrapper
# ##############语法糖######################
@logger
def say_hello(name):
print(f"你好, {name}!")
say_hello("李四")
# 执行函数: say_hello
# 你好, 李四!
# 函数 say_hello 执行完毕。