from functools import wraps
# def a_new_decorator(a_func):
# @wraps(a_func)
# 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
# @a_new_decorator
# def a_function_requiring_decoration():
# """Hey yo !DECORATE ME"""
# print("I am the function which needs some decoration to remove my foul smell")
# print(a_function_requiring_decoration.__name__)
from functools import wraps
def decorator_name(f):
@wraps(f)
def decorated(*args,**kwargs):
if not can_run:
return "Fuction 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())
# 注意:@wraps接受一个函数来进行装饰,
# 并加入了复制函数名称、注释文档、参数列表等等的功能。
# 这可以让我们在装饰器里面访问在装饰之前的函数的属性。
# 使用场景
# 授权(Authorization)
# 装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint)。
# 它们被大量使用于Flask和Django web框架中。这里是一个例子来使用基于装饰器的授权:
def requires_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
日志(Logging)
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 calle
# 带参数的装饰器
# 来想想这个问题,难道@wraps不也是个装饰器吗?
# 但是,它接收一个参数,就像任何普通的函数能做的那样。
# 那么,为什么我们不也那样做呢?
# 这是因为,当你使用@my_decorator语法时,
# 你是在应用一个以单个函数作为参数的一个包裹函数。
# 记住,Python里每个东西都是一个对象,
# 而且这包括函数!记住了这些,
# 我们可以编写一下能返回一个包裹函数的函数。
from functools import wraps
def logit(logfile='out.log'):
def logging_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# 打开logfile,并写入内容
with open(logfile, 'a') as opened_file:
# 现在将日志打到指定的logfile
opened_file.write(log_string + '
')
return func(*args, **kwargs)
return wrapped_function
return logging_decorator
@logit()
def myfunc1():
pass
myfunc1()
# Output: myfunc1 was called
# 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串
@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)
# # 打开logfile并写入
# 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):
# # logit只打日志,不做别的
# pass
# 这个实现有一个附加优势,在于比嵌套函数的方式更加整洁,
# 而且包裹一个函数还是使用跟以前一样的语法:+
#
# @logit()
# def myfunc1():
# pass
# 现在,我们给logit创建子类,来添加email的功能(虽然email这个话题不会在这里展开)。
# class email_logit(logit):
# '''
# 一个logit的实现版本,可以在函数调用时发送email给管理员
# '''
# def __init__(self, email='admin@myproject.com', *args, **kwargs):
# self.email = email
# super(email_logit, self).__init__(*args, **kwargs)
#
# def notify(self):
# # 发送一封email到self.email
# # 这里就不做实现了
# pass
# 从现在起,@email_logit将会和@logit产生同样的效果,
# 但是在打日志的基础上,还会多发送一封邮件给管理员。