zoukankan      html  css  js  c++  java
  • 我终于弄懂了Python的装饰器(四)

    此系列文档:

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

    2. 我终于弄懂了Python的装饰器(二)

    3. 我终于弄懂了Python的装饰器(三)

    4. 我终于弄懂了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>
    

    现在,您可以暂时放下开心的心情,我们来动动脑筋,看看装饰器的高级用法。


    原文链接:https://stackoverflow.com/questions/739654/how-to-make-a-chain-of-function-decorators

    本文首发于BigYoung小站

  • 相关阅读:
    postgresql postgres.Jsonb
    gorm jsonb
    json
    postgresql重置序列和自增主键
    go build x509: certificate has expired or is not yet valid
    权限修饰符
    交换两个变量的值
    Java编译报错:编码GBK的不可映射字符
    原码反码补码的理解
    Scanner类中hasNext()方法的解析
  • 原文地址:https://www.cnblogs.com/bigyoung/p/13278041.html
Copyright © 2011-2022 走看看