简介
- 装饰器:在不修改被装饰函数的代码情况下,增强其功能。这个类似于Java中的面向切片编程。它本质也是一个函数,接受一个被装饰函数作为参数,返回增强版的与被装饰函数同名的函数
- 闭包是装饰器的基础,python中的闭包详见python之函数与闭包
装饰器的实现
- 装饰器的语法如下:
- 使用语法糖:在被装饰的函数之前加上@装饰器函数名或者在被装饰的类之上加上@装饰器类名。这个常用
@decorator
def decorated_function():
pass
- 显示的调用装饰器。如果在一个函数上需要使用多个装饰器,这种写法可读性差
def decorated_function():
pass
decorated_function = decorator(decorated_function)
- 用函数实现装饰器。
- 简单的示例如下所示:
from loguru import logger
def my_decorator(function):
'''
function为被装饰函数
'''
def wrapped(*args, **kwargs):
logger.info(f'日志记录开始')
ret = function(*args, **kwargs)
logger.info(f'日志记录结束')
return ret
return wrapped
def login(user_name, password):
if user_name == 'admin' and password == '123456':
print('login success')
else:
print('login failed')
login = my_decorator(login)
login('admin', '123456')
- 带参数的装饰器:在装饰器之上再套一个函数
from loguru import logger
def my_decorator_plus(type):
def my_decorator(function):
def wrapper(*args, **kwargs):
if type == 0:
logger.info(f'微信登录日志记录开始')
ret = function(*args, **kwargs)
logger.info(f'微信登录日志记录结束')
elif type == 1:
logger.info(f'QQ登录日志记录开始')
ret = function(*args, **kwargs)
logger.info(f'QQ登录日志记录结束')
return ret
return wrapper
return my_decorator
@my_decorator_plus(0)
def login(user_name, password):
if user_name == 'admin' and password == '123456':
print('login success')
else:
print('login failed')
login('admin', '123456')
- 自定义类实现装饰器。
- __call__方法介绍:这个方法可以将类的实例化对象转化成可调用对象。可调用对象可以直接调用__call__方法或者以
对象名称()
的形式调用。示例如下:
class Student:
def __init__(self, name):
super().__init__()
self.name = name
def __call__(self):
print('hi,' + f'{self.name}')
stu = Student("zss")
print(callable(stu))
stu.__call__()
stu()
- 实现的类装饰器如下所示
from typing import Any
from loguru import logger
class MyDecorator:
def __init__(self, function) -> None:
self.function = function
def __call__(self, *args: Any, **kwds: Any) -> Any:
logger.info('日志记录开始')
ret = self.function(*args, **kwds)
logger.info(f'日志记录结束')
return ret
@MyDecorator
def login(user_name, password):
if user_name == 'admin' and password == '123456':
print('login success')
else:
print('login failed')
login('admin', '123456')
装饰器的应用场景
1.在方法定义的开头能够将其定义为类方法或者静态方法
- 不使用装饰器前,手动将函数转化为类方法或者静态方法
class Test:
def clsFunc(cls):
print("this is class Method")
def staFunc():
print("this is static Method")
clsMethod = classmethod(clsFunc)
staMethod = staticmethod(staFunc)
Test.clsMethod()
Test.staMethod()
- 使用装饰器后,方便将函数转化为类方法或者静态方法。如下示例使用了
@classmethod
和@staticmethod
两个装饰器,被装饰函数分别为clsFunc和staFunc
class Test:
@classmethod
def clsFunc(cls):
print("this is class Method")
@staticmethod
def staFunc():
print("this is static Method")
Test.clsFunc()
Test.staFunc()
2.上下文装饰器
- 上下文装饰器确保函数可以运行在正确的上下文中,或者在函数前后运行一些代码。
from threading import RLock
lock = RLock()
def synchronized(function):
def _synchronized(*args, **kw):
lock.acquire()
try:
return function(*args, **kw)
finally:
lock.release()
return _synchronized
@synchronized
def thread_salf():
pass
3.@property装饰器
- 装饰器:在代码运行期间动态增加函数或者方法。在类中的方法使用
@property
修饰,则会将该属性作为类属性,可以像属性一样的方式通过对象.方法名
或者类名.方法名
来访问方法。
- 示例如下:
class Student:
def __init__(self, name):
self.__name = name
@property
def name(self):
return self.__name
stu = Student("zss")
print(stu.name)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)