此系列文档:
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 自身提供了一些装璜:property
,staticmethod
,等。
- 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/que…
本文首发于 BigYoung 小站