Python装饰器的使用

本文深入探讨了Python装饰器的原理和使用,包括函数装饰器、类装饰器及如何使用多个装饰器。通过案例展示了装饰器在登录检测、函数执行时间记录和参数合理性检查等实际场景的应用,强调了装饰器在代码复用和功能增强上的优势。
摘要由CSDN通过智能技术生成

1 装饰器

1.2 函数装饰器

所谓的装饰器,其实是通过装饰器函数,来修改原函数的一些功能,而原函数本身并不进行修改。
在这里插入图片描述
下面的示例中,使用装饰器在原函数前进行打印语句。

import functools

def my_decorator(func):
    @functools.wraps(func) # 将原函数func的元信息,拷贝到wrapper中的
    def wrapper(*args,**kwargs):
        print('this is a wrapper')
        func(*args)
    return wrapper

@my_decorator # @为语法糖
def greet(name):
    print('welcome {}!'.format(name))

@my_decorator
def greet_two(name1,name2):
    print('welcome {} and {}!'.format(name1,name2))

greet([5,24,2])
greet_two([5,24,2],'234')

# 如果不适用functools.wraps装饰器,原函数中的元信息将会被改变
print(greet.__name__)
print(help(greet))
this is a wrapper
welcome [5, 24, 2]!
this is a wrapper
welcome [5, 24, 2] and 234!
greet
Help on function greet in module __main__:

greet(name)

None

使用装饰器将会修改原函数的元信息,我们可以通过系统装饰器functools.wraps来保持元信息。

1.2 类装饰器

"""
类装饰器的使用
"""
class Count():
    def __init__(self,func):
        self.func=func
        self.num=0

    def __call__(self, *args, **kwargs):
        self.num+=1
        print('num:{}'.format(self.num))
        self.func(*args,**kwargs)

@Count
def example(message):
    print('message:{}'.format(message))

example('hello')

example('nihao')
num:1
message:hello
num:2
message:nihao

1.3 使用多个装饰器

我们可以对一个函数使用多个装饰器,顺序为从内到外。

import functools

def decorator1(func):
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
        print('decorator one')
        func(*args,**kwargs)
    return wrapper

def decorator2(func):
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
        print('decorator two')
        func(*args,**kwargs)
    return wrapper

@decorator1
@decorator2
def greet(message):
    print('message:',message)

greet('hello world')
decorator one
decorator two
message: hello world

1.4 案例

1.4.1 案例1-发表评论

在博客网站或是视频网站发表评论前,我们要先检测用户是否登录,确认登陆后才能发表评论。在此使用装饰器进行登陆的检测。

"""
用装饰器实现:
发表评论前检测是否登录,已登录则发表评论,否则抛出异常
"""
import functools

def check_user_logged_in(request):
    return 1 if request>10 else 0

def authenticate(func):
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
        request=args[0]
        if check_user_logged_in(request): # 如果用户是登录状态
            func(*args,**kwargs) # 执行方法post_comment()
        else:
            raise Exception('Authentication failed')
    return wrapper

@authenticate
def post_comment(request, comment):
    print('comment successfully:',comment)

post_comment(11,'what a wonderful blog!')
comment successfully: what a wonderful blog!
1.4.2 案例2-记录执行时间

通过装饰器,我们可以记录任意函数的执行时间。

"""
案例2:使用装饰器实现测试任意函数的执行时间
"""
import functools
import time

def log_execute_time(func):
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
        start=time.time()
        func(*args,**kwargs)
        end=time.time()
        print('time cost:%.2f' %(end-start))
    return wrapper

@log_execute_time
def calculate_similarity():
    count=1
    for i in range(int(1e6)):
        count+=1

calculate_similarity()

time cost:0.08
1.4.3 案例3-参数合理性检测

在训练神经网络模型时,这个过程往往是非常耗时的,如果花费了几个小时,最后因为参数的不合理而产生报错,就会对资源造成极大的浪费。
在此我们使用装饰器对训练参数进行合理性检测。

"""
在神经网络模型进行训练前,进行参数合理性检查
"""
import functools

def validation_check(func):
    @functools.wraps(func)
    def wrapper(*args,**kwargs):# 这里进行简单的输入类型检查
        for idx,param in enumerate(args):
            if not isinstance(param,float):
                raise Exception('Parameter format wrong in pos:{}'.format(idx+1))
        for idx,key in enumerate(kwargs):
            if key=='optimizer' and kwargs[key] not in ['Adam','SGD']:
                raise Exception('Keyword parameter format wrong in pos:{}'.format(idx+1+len(args)))
        func(*args,**kwargs)
    return wrapper

@validation_check
def neural_network_training(l2,lr,dropout,optimizer='SGD'):
    print('start training...')
    print('l2:{}'.format(l2))
    print('learning rate:{}'.format(lr))
    print('dropout rate:{}'.format(dropout))
    print('optimizer:{}'.format(optimizer))

neural_network_training(0.5,0.001,0.2,optimizer='SGD')
start training...
l2:0.5
learning rate:0.001
dropout rate:0.2
optimizer:SGD
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值