装饰器——面向切面的编程

先甩上参考链接:参考教程
装饰器本身是为了避免相似处理代码的重复的简化处理。

最原始的使用:

def a_new_decorator(a_func):
    @wraps(a_func)          #从wraps函数可以发现 decorator函数可以传参 
    def wrapTheFunction():
        print('I am doing some boring work before executing a_func()')
        a_func()
        print('I am doing some boring work after executing a_func()')

    return wrapTheFunction
  
def a_function_require_decorator():
print('I am the function who needs some decoration to remove mu foul smell')

a_new_decorator(a_function_require_decorator)()
print(a_function_require_decorator.__name__)  

output:
I am doing some boring work before executing a_func()
I am the function who needs decorator to remove foul smell
I am doing some boring work after executing a_func()
wrapTheFunction

为了可以正确输出函数的__name__, 使用@wraps decorator函数。
因为这种写法模糊了这个函数到底要干什么的重点,所以引入语法糖@

@a_new_decorator
def a_function_require_decorator():
    print('I am the function who needs decorator to remove foul smell')

a_function_require_decorator()

这种方式结构清晰明了,将装饰器的部分都藏了起来,最后运行的时候只需运行这个函数。

# 规范写法
from functools import wraps
def decorator_name(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if not can_run:
            return 'Function will not run'
        return f(*args, **kwargs)
    return decorated

@decorator_name
def func():
    return 'Function is running'

can_run = True
print(func())

can_run = False
print(func())

使用场景

1.授权(authorization)

检查某个人是否被授权使用某个web应用的端点(endpoint),常用于Flask和Django web框架。
#用于web授权的场景

from functools import wraps
def require_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth or not check_auth(auth_username, auth.password):
            authenticate()
        return f(*args, **kwargs)
    return decorated

2.日志

from functools import wraps
 
def logit(func):
    @wraps(func)
    def with_logging(*args, **kwargs):
        print(func.__name__ + " was called")
        return func(*args, **kwargs)
    return with_logging
 
@logit
def addition_func(x):
   """Do some math."""
   return x + x
 
 
result = addition_func(4)
# Output: addition_func was called

带参数的装饰器

在函数中嵌入装饰器

@my_decorator 语法实际返回一个以某个单个函数为参数的包裹参数。我们可以通过函数嵌套,使最外层函数可以传参,并且返回包裹函数。

#带参数的装饰器
from functools import wraps
def logit(logfile='out.log'):
    def logging_decorator(f):
        @wraps(f)
        def wrapped_function(*args, **kwargs):  这里传入的参数为f的参数
        										args为位置参数 kwargs为关键字参数
            log_string = f.__name__ + ' was_called'
            print(log_string)

            with open(logfile, 'a') as opened_file:
                opened_file.write(log_string)
            return f(*args, **kwargs) 在这里执行f
        return wrapped_function
    return logging_decorator

@logit()
def my_func():
    pass

my_func()
#output:my_func was_called	

@logit(logfile='func2.log')
def myfunc2():
    pass
 
myfunc2()
# Output: myfunc2 was called
# 现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串

装饰器类

现在我们有了能用于正式环境的logit装饰器,但当我们的应用的某些部分还比较脆弱时,异常也许是需要更紧急关注的事情。比方说有时你只想打日志到一个文件。而有时你想把引起你注意的问题发送到一个email,同时也保留日志,留个记录。这是一个使用继承的场景,但目前为止我们只看到过用来构建装饰器的函数。

幸运的是,类也可以用来构建装饰器。那我们现在以一个类而不是一个函数的方式,来重新构建logit

# 装饰器类
from functools import wraps
class logit(object):
    def __init__(self, logfile='out.log'):
        self.logfile = logfile
    def __call__(self, func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            log_string = func.__name__ + ' was called'
            print(log_string)
            with open(self.logfile, 'a') as opened_file:
                opened_file.write(log_string)
            self.notify()
            return func(*args, **kwargs)
        return wrapped_function
    def notify(self):
        pass

@logit()
def my_func1():
    pass

my_func1()

class logit_email(logit):
    def __init__(self,email = 'admin@myproject.com', *args, **kwargs):
        self.email = email
        super(logit_email, self).__init__(*args, **kwargs) 
        #注意继承类时super后面的表达 args和kwargs的使用
    def notify(self):
        # 发送一封email到self.email
        pass

@logit_email()
def my_func2():
    pass

my_func2()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值