此系列文档:

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_argumentsdef 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_argumentsdef 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_argumentsdef 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,而是wrapperdef bar(func):    def wrapper():        print("bar")        return func()    return wrapper@bardef foo():    print("foo")print(foo.__name__)#输入: wrapper# "functools" can help for thatimport functoolsdef bar(func):    # We say that "wrapper", is wrapping "func"    # and the magic begins    @functools.wraps(func)    def wrapper():        print("bar")        return func()    return wrapper@bardef 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 italicdef makeitalic(fn):    # The new function the decorator returns    def wrapper():        # Insertion of some code before and after        return "<i>" + fn() + "</i>"    return wrapper@makebold@makeitalicdef 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/que...

本文首发于BigYoung小站