PythonStudy——装饰器 Decorator

时间:2024-12-01 08:36:01
def outer(func):
  def inner():
    print("新增功能1")
    func()
    print("新增功能2")
  return inner

@outer # 这个一定要写!!func = outer(func)= inner
def func():   
  print("原有功能")

# 装饰器:满足开放封闭原则的一个闭包应用


# @outer语法来调用outer,规定传入被装饰的函数对象,所以参数固定为一个,接受被装饰的函数对象
def outer(func):
# 不能确定被装饰的函数的参数:来者不拒,用可边长来接受
  def inner(*args, **kwargs):
    pass # 新功能位
    res = func(*args, **kwargs) # 解压带给原功能
    pass # 新功能位
    return res
  return inner


# 使用装饰器(outer),得到新功能(inner)


# 用被装饰的函数名去接受装饰器的执行结果,调用装饰器时传入被装饰的函数对象
@outer # fn = outer(fn) = inner
def fn():

  pass


# 表面感觉调用的是原函数,本质调用的是闭包(inner),使用fn调用和fn定义及inner需要参数统一
fn()

 
def wrap(func):
def inner(*args, **kwagrs):
# res = func(*args, **kwagrs)
res = outer.inner()
return res
return inner def outer(func):
def inner(*args, **kwagrs):
pass
res = func(*args, **kwagrs)
pass # res
return res
return inner @wrap # fn = warp(fn) = wrap(outer.inner) = wrap.inner
@outer # fn = outer(fn) = outer.inner
def fn(n1, n2, n3): pass fn(1, 2, 3)

装饰器语法糖

def outer(func):
def inner():
print("新增功能1")
func()
print("新增功能2")
return inner @outer
def func():
print("原有功能")

装饰有参有返的函数

def outer(func):
def inner(*args, **kwargs):
print("新增功能1")
result = func(*args, **kwargs)
print("新增功能2")
return result
return inner @outer
def func(*args, **kwargs):
print("原有功能")
return "原有结果"

有参装饰器

def wrap(arg):
def outer(func):
def inner(*args, **kwargs):
print("新增功能1")
result = func(*args, **kwargs)
print("新增功能2")
return result
return inner @wrap("装饰器参数")
def func(*args, **kwargs):
print("原有功能")
return "原有结果"

wraps修改函数文档注释

from functools import wraps
def outer(func):
@wraps(func)
def inner(*args, **kwargs):
'''装饰器文档注释'''
func(*args, **kwargs)
return inner @outer
def func(*args, **kwargs):
'''原有文档注释'''
print("原有功能")

一个函数被多次装饰

def outer(func):
def inner(*args, **kwargs):
res = func(*args, **kwargs)
return res
return inner def check_user(func):
def inner(*args, **kwargs):
# 账号的验证功能
user = args[0] # type: str
if not (user.isalpha() and len(user) >= 3):
print('账号不合法')
return False res = func(*args, **kwargs)
return res
return inner def check_pwd(func):
def inner(*args, **kwargs):
pwd = args[1]
if len(pwd) < 3:
print('密码不合法')
return False res = func(*args, **kwargs)
return res
return inner def format_return(func):
def inner(*args, **kwargs):
res = func(*args, **kwargs)
if res:
return '登录成功'
return '登录失败'
return inner # 登录的原功能 @format_return
@check_user
@check_pwd
def login(user, pwd):
if user == 'owen' and pwd == '':
return True
return False user = input('user: ')
pwd = input('pwd: ')
res = login(user, pwd)
print(res) # 执行过程:调用login => 进入第一个装饰器(format_return)的inner => 进入第二个装饰器(check_user)的inner => 进入第三个装饰器(check_pwd)的inner => 开始返回,从第三个返回到第二个再返回到第一个,最后返回到外界调用的位置

 # 系统的wraps带参装饰器:改变inner的假指向,本质外界使用的还是inner,但是打印显示的是wraps中的函数

from functools import wraps
def outer(func):
@wraps(func)
def inner(*args, **kwargs):
res = func(*args, **kwargs)
return res
return inner @outer
def fn():
  pass