python中的装饰器

装饰器(Decorators)是Python的一个重要部分。简单地说:他们是修改其他函数功能的函数。他们有助于让我们的代码简短,也更符合Python规范(Pythonic)。

def a_new_decorator(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 wrapTheFunctiondef a_function_requiring_decoration(): print(“I am the function which needs some decoration to remove my foul smell”)a_function_requiring_decoration()#outputs: “I am the function which needs some decoration to remove my foul smell”a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)#now a_function_requiring_decoration is wrapped by wrapTheFunction()a_function_requiring_decoration()#outputs:I am doing some boring work before executing a_func()# I am the function which needs some decoration to remove my foul smell# I am doing some boring work after executing a_func()

上面的代码可以更简洁一些:

def a_new_decorator(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_decoratordef a_function_requiring_decoration(): print(“I am the function which needs some decoration to remove my foul smell”)a_function_requiring_decoration()#outputs:I am doing some boring work before executing a_func()# I am the function which needs some decoration to remove my foul smell# I am doing some boring work after executing a_func()

其中@a_new_decorator(注意语句位置,须位于被装修函数之前)等价于下列语句:

a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)

如果需要获取被装饰函数的函数名,需要使用functools.wraps函数:

from functools import wrapsdef 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_decoratordef 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__)# Output: a_function_requiring_decoration

否则,print(a_function_requiring_decoration.__name__)的返回结果将是wrapTheFunction。

装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint)。它们被大量使用于Flask和Django web框架中。这里是一个例子来使用基于装饰器的授权:

from functools import wrapsdef 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

日志是装饰器运用的另一个亮点。这是个例子:

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

装饰器也可以带参数,我们将上面日志的例子修改一下,允许指定保存日志的位置:

from functools import wrapsdef logit(logfile=’out.log’): def logging_decorator(func): @wraps(func) def wrapped_function(*args, **kwargs): log_string = func.__name__ + ” was called” print(log_string) # Open the logfile and append with open(logfile, ‘a’) as opened_file: # Now we log to the specified logfile opened_file.write(log_string + ”) return func(*args, **kwargs) return wrapped_function return logging_decorator@logit()def myfunc1(): passmyfunc1()# Output: myfunc1 was called# A file called out.log now exists, with the above string@logit(logfile=’func2.log’)def myfunc2(): passmyfunc2()# Output: myfunc2 was called# A file called func2.log now exists, with the above string

类也可以用来构建装饰器:

class logit(object): _logfile = ‘out.log’ def __init__(self, func): self.func = func def __call__(self, *args): log_string = self.func.__name__ + ” was called” print(log_string) # Open the logfile and append with open(self._logfile, ‘a’) as opened_file: # Now we log to the specified logfile opened_file.write(log_string + ”) # Now, send a notification self.notify() # return base func return self.func(*args) def notify(self): # logit only logs, no more pass

这个实现有一个附加优势,在于比嵌套函数的方式更加整洁,而且包裹一个函数还是使用跟以前一样的语法:

logit._logfile = ‘out2.log’ # if change log file@logitdef myfunc1(): passmyfunc1()# Output: myfunc1 was called

我们给logit创建子类,来添加email的功能。

class email_logit(logit): ”’ A logit implementation for sending emails to admins when the function is called. ”’ def __init__(self, email=’admin@myproject.com’, *args, **kwargs): self.email = email super(email_logit, self).__init__(*args, **kwargs) def notify(self): # Send an email to self.email # Will not be implemented here pass

郑重声明:本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系管理员(admin#wlmqw.com)删除。
(0)
用户投稿
上一篇 2022年6月19日
下一篇 2022年6月19日

相关推荐

联系我们

联系邮箱:admin#wlmqw.com
工作时间:周一至周五,10:30-18:30,节假日休息