专栏首页BigYoung小站我终于弄懂了Python的装饰器(四)

我终于弄懂了Python的装饰器(四)

四、装饰器的用法

通用装饰器

如要制作通用装饰器(无论参数如何,您都可以将其应用于任何函数或方法),则只需使用*args, **kwargs

建议先看看*args, **kwargs用法:

链接:Python中 *args 和 **kwargs的用法

def a_decorator_passing_arbitrary_arguments(function_to_decorate):
    #包装器接受任何参数
    def a_wrapper_accepting_arbitrary_arguments(*args, **kwargs):
        print("Do I have args?:")
        print(args)
        print(kwargs)
        function_to_decorate(*args, **kwargs)
    return a_wrapper_accepting_arbitrary_arguments

@a_decorator_passing_arbitrary_arguments
def function_with_no_argument():
    print("Python is cool, no argument here.")

function_with_no_argument()
#输出:
#Do I have args?:
#()
#{}
#Python is cool, no argument here.

@a_decorator_passing_arbitrary_arguments
def function_with_arguments(a, b, c):
    print(a, b, c)

function_with_arguments(1,2,3)
#输出:
#Do I have args?:
#(1, 2, 3)
#{}
#1 2 3 

@a_decorator_passing_arbitrary_arguments
def function_with_named_arguments(a, b, c, platypus="Why not ?"):
    print("Do {0}, {1} and {2} like platypus? {3}".format(a, b, c, platypus))

function_with_named_arguments("Bill", "Linus", "Steve", platypus="Indeed!")
#输出:
#Do I have args ? :
#('Bill', 'Linus', 'Steve')
#{'platypus': 'Indeed!'}
#Do Bill, Linus and Steve like platypus? Indeed!

class Mary(object):

    def __init__(self):
        self.age = 31

    @a_decorator_passing_arbitrary_arguments
    def sayYourAge(self, lie=-3): # You can now add a default value
        print("I am {0}, what did you think?".format(self.age + lie))

m = Mary()
m.sayYourAge()
#输出:
# Do I have args?:
#(<__main__.Mary object at 0xb7d303ac>,)
#{}
#I am 28, what did you think?

最佳做法:装饰器

注意:

  • 装饰器是在Python 2.4中引入的,因此请确保您的代码将在> = 2.4上运行。
  • 装饰器使函数调用变慢。(请记住这点)
  • 您不能取消装饰功能。(有一些技巧,可以创建可以被删除的装饰器,但是没有人使用它们。)因此,一旦装饰了一个函数,就对所有代码进行了装饰。
  • 装饰器包装函数,这会使它们难以调试。(这在Python> = 2.5时有所调整;请参见以下内容。)

functools模块是在Python 2.5中引入的。它包括函数functools.wraps(),该函数将修饰后的函数的名称,模块和文档字符串复制到其包装器中。

(有趣的事是:functools.wraps()也是一个装饰器!)

#为了进行调试,stacktrace将向您显示函数__name__
def foo():
    print("foo")

print(foo.__name__)
#输出: foo

#使用装饰器时,输出的信息会变得凌乱,不再是foo,而是wrapper
def bar(func):
    def wrapper():
        print("bar")
        return func()
    return wrapper

@bar
def foo():
    print("foo")

print(foo.__name__)
#输出: wrapper

# "functools" can help for that

import functools

def bar(func):
    # We say that "wrapper", is wrapping "func"
    # and the magic begins
    @functools.wraps(func)
    def wrapper():
        print("bar")
        return func()
    return wrapper

@bar
def foo():
    print("foo")

print(foo.__name__)
#outputs: foo

Python本身提供了一些装饰:propertystaticmethod,等。

  • Django使用装饰器来管理缓存和查看权限。
  • 伪造的内联异步函数调用。

如何使用链式装饰器?

# 大胆的使用链式装饰器吧
def makebold(fn):
    # The new function the decorator returns
    def wrapper():
        # Insertion of some code before and after
        return "<b>" + fn() + "</b>"
    return wrapper

# The decorator to make it italic
def makeitalic(fn):
    # The new function the decorator returns
    def wrapper():
        # Insertion of some code before and after
        return "<i>" + fn() + "</i>"
    return wrapper

@makebold
@makeitalic
def say():
    return "hello"

print(say())
#输出: <b><i>hello</i></b>

# This is the exact equivalent to 
def say():
    return "hello"
say = makebold(makeitalic(say))

print(say())
#输出: <b><i>hello</i></b>

本文分享自微信公众号 - BigYoung小站(bigyoungs),作者:Young文人

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-07-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 我终于弄懂了Python的装饰器(一)

    好吧,您只具备了解装饰器所需的所有信息。您会看到,装饰器是“包装器(wrappers)”,这意味着**它们使您可以在装饰函数之前和之后执行代码,**而无需修改函...

    BigYoung小站
  • Exchange2013通讯组授权其他用户管理其中成员方法

    公司里的通讯组超级多,总是有员工申请更改通讯组中的成员,为了简化管理员的工作,可以把经常变更群组成员的群组管理员分配给相应的人员。

    BigYoung小站
  • Python 3 查看字符编码方法

    BigYoung小站
  • 初学python,调用固定参,不固定参

    函数调用时的参数传递方式:(调用函数) 传递方式有以下四种: 位置传参 序列传参 关键字传参 字典关键字传参 -------------------------...

    py3study
  • python之抽象一

    num = input('How many Fibonacci numbers do you want?')

    py3study
  • Python Day3

    #如果是windows平台一般还要加上一个小r,意思是取消路径中/的转义功能(不用写//了) #默认t,指的是文本文件,文本里面存放的是字符,因此涉及到字符编码...

    py3study
  • python3–装饰器

    老七Linux
  • 被房产大佬看上,AR家居Hutch获融资1000万美元

    镁客网
  • 使用python的zabbix_api模

    使用python的zabbix_api模块,以下是简单的zabbix api的使用

    py3study
  • python菜鸟教程 | if else 判断

    当 if 判断条件为 True,执行 true_expressions 语句; 如果为 False,将执行 else 的内部的 false_expression...

    week

扫码关注云+社区

领取腾讯云代金券