Python 装饰器,且看以下案例:def


Python 装饰器

python装饰器的本质是: 仅以一个函数为参数,并返回一个函数。 且看以下案例:

def decorator(f):
	print(f.__name__)
	return f

# 1
@decorator
def fun():
	print("run fun")
# 2
fun = decorator(fun)

以上两种写法是等价的;装饰器函数会在被装饰的函数 定义完成时执行。

装饰器优点:

  • 不会改变被装饰函数的调用
  • 不用修改被装饰函数的代码

根据使用场景装饰器可以分为几种:

一次性装饰器

一次性装饰器;不对被装饰函数进行任何操作,原样返回被装饰的函数;仅在被装饰函数定义时进行操作。

funcs = []

def decorator(f):
	funcs.append(f)	# 将函数保存到全局list中去
	return f

@decorator
def fun():
	print("run fun")

包装装饰器

包装装饰器;一般是在被装饰函数执行前后做一些额外的操作,或者对被装饰函数计算的结果进行操作。

import time

def decorator(f):
	def wrapper(*args, **kwds): # 不确定被装饰函数的参数,使用万能形参
		t1 = time.time()
		result = f(*args, **kwds) # 执行被装饰函数
		t2 = time.time()
		print(f.__name__, "执行耗时", t2-t1)
		return result
	return wrapper

@decorator
def fun():
	time.sleep(2)
	print("run fun")
# fun = decorator(fun)
# 此时 fun 已经变成了 wrapper 函数;已经被decorator返回的wrapper覆盖

配置装饰器

即有带参数的装饰器,此装饰器可能是为了给被装饰函数提供额外的信息;或者需要用户自己添加配置。
我们只看wrapper函数是不是和上文的一次性装饰器一样呢

def decorator(name):
	def wrapper(f):
		f.name = name
		return f
	return wrapper

@decorator("fun1")
def fun():
	print("run fun")
# fun = decorator("fun1")(fun)

print(fun.name)
fun()

配置包装装饰器

配置包装装饰器,即有装饰器配置项和修改被包装函数执行流程的装饰器;

import time

def decorator(name): # 配置选项
	def setname(f): # 包装被装饰的函数
		f.name = name  # 闭包获取 配置选项
		def wrapper(*args, **kwds): # 返回的最终函数
			t1 = time.time()
			result = f(*args, **kwds) # 执行被包装的函数
			t2 = time.time()
			print(f.name, "执行耗时", t2-t1)
			return result
		return wrapper
	return setname

@decorator("fun1")
def fun():
	print("run fun")

类装饰器

@decorator本质是一次函数调用;对应到类上就是__init__()调用;即类的实例化。如果类实现了__call__()方法,类的实例对象就可以像函数一样调用。

class Decorator:
	def __init__(self, name):
		self.name = name
	
	def __call__(self, f):
		self.f = f
		return self.wrapper
	
	def wrapper(self, *args, **kwds):
		print(self.name)
		return self.f(*args, **kwds)
@Decorator("name")
def fun():
	print("run fun")

装饰类的装饰器

def decorator(cls):
	def wrapper(*args, **kwds):
		obj = cls(*args, **kwds)
		return obj
	return wrapper

@decorator
class Test:
	def __init__(self):
		pass

print(Test)
print(Test())

# <function decorator.<locals>.wrapper at 0x7fd9ecba5280>
# <__main__.Test object at 0x7fd9ecc22550>

多层装饰器

def a(f):
	print("a 装饰器执行")
	def _a():
		print("函数执行 调用_a 装饰器")
		return f()
	return _a

def b(f):
	print("b 装饰器执行")
	def _b():
		print("函数执行 调用_b 装饰器")
		return f()
	return _b
	
def c(f):
	print("c 装饰器执行")
	def _c():
		print("函数执行 调用_c 装饰器")
		return f()
	return _c

@a
@b
@c
def fun():
	print("fun run")
# fun = a( b( c(fun )) )
fun()
# -----程序输出—-----
# c 装饰器执行
# b 装饰器执行
# a 装饰器执行
# 函数执行 调用_a 装饰器
# 函数执行 调用_b 装饰器
# 函数执行 调用_c 装饰器
fun run

有什么建议意见请留言讨论

谢谢观看

浪费了你人生中的几秒真的很抱歉(≧ ﹏ ≦)

结局早已注定,命运无法违抗

评论关闭