前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你的第一个装饰器是怎么写的

你的第一个装饰器是怎么写的

作者头像
Python知识大全
发布2020-02-21 15:58:24
4090
发布2020-02-21 15:58:24
举报
文章被收录于专栏:Python 知识大全

" 本文字数:1016 字 ||

阅读时间3 分钟"

其实我们已经创建了一个装饰器! 一切皆对象,那是我的对象

现在我们修改下上一个装饰器,并编写一个稍微更有用点的程序:

代码语言:javascript
复制
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

def 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()

这正是 Python 中装饰器做的事情!

它 们封装一个函数,并且这样或者那样的方式来修改它的行。现在你也许疑惑,我们在代码里并没有使用@符号?那只是一个简短的方式来生成一个被装饰的函数。

这里是我们如何使用@来运行之前的代码:

代码语言:javascript
复制
@a_new_decorator
def a_function_requiring_decoration():
    """Hey you! Decorate me!"""
    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()
#the @a_new_decorator is just a short way of saying:
a_function_requiring_decoration = a_new_decorator(a_function_requiri

希望你现在对 Python 装饰器的工作原理有个基本的理解。

如果我们运行如下代码会存在 一个问题:

代码语言:javascript
复制
print(a_function_requiring_decoration.__name__)
# Output: wrapTheFunction

这并不是我们想要的!

Ouput输出应该是“a_function_requiring_decoration”。这里的函数被 warpTheFunction替代了。它重写了我们函数的名字和注释文档(docstring)。幸运的是 Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps。

我们修改上一个例子来使用functools.wraps:

代码语言:javascript
复制
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__)
# Output: a_function_requiring_decoration

现在好多了。

我们接下来学习装饰器的一些常用场景。

代码语言:javascript
复制
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())
# Output: Function is running
can_run = False
print(func())
# Output: Function will not run

注意:@wraps接受一个函数来进行装饰,并加个了复制函数名称、注释文档、参数列表 等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python 知识大全 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档