在写这个问题之前,我已经提到了以下一些有趣的问题,并认为这个场景没有解释/涵盖:
我有function
如下:
def simple_function():
print 'this is a simple_function'
而且,我有以下class
一些methods
class Test:
def Test_method_1(self, func, args=None, kwargs=None):
print 'this is Test::Test_method_1'
<execute some instructions here>
def Test_method_2(self):
print 'this is Test::Test_method_2'
我正在使用Test_method_1
和simple_function
,如下所示:
t = Test()
t.Test_method_1(simple_function)
假设simple_function
采用任意参数,则调用Test_method_1
如下:
def simple_function(a, b, c, d=f, g=h):
print 'this is a simple_function'
t = Test()
t.Test_method_1(simple_function, args=[a, b, c], kwargs={d:f, g:h})
现在,我想将Test_method_2
用作decorator version
的{{1}}。所以Test_method_1
定义可以写成如下:
simple_function
注意:t = Test()
@t.Test_method_2
def simple_function():
print 'this is a simple_function'
将使用适当的参数调用Test_method_2
。
Test_method_1
)作为参数传递给simple_function
(包括Test_method_2
)?self
(装饰者)和Test_method_2
(正在装饰的函数) - simple_function
- 如何定义*args and **kwargs
来接收参数(包括Test_method_2
)?使用self
作为Test_method_2
的装饰器以及两者的任意参数如下:
simple_function
答案 0 :(得分:1)
当然有可能。所有@decorator
语法都定义了后面的函数,然后调用装饰器,传入后面的函数并用返回的函数替换对该函数的引用。
以下内容:
@foo
def bar():
pass
被翻译为:
def bar():
pass
bar = foo(bar)
这意味着你的t.Test_method_2()
方法必须要有一个参数,即待装饰的函数,并返回一些可调用的东西:
import functools
def Test_method_2(self, func):
@functools.wraps(func)
def wrapper(self, *args, **kw):
print 'Wrapped function name:', func.__name__
return func(*args, **kw)
return wrapper
将是返回包装函数的最小装饰器,并在调用时打印包装函数的名称。参数被称为并不重要;我在这里使用了func
,但它可以是任何合法的python标识符。
self
是方法签名的标准部分。因为您在实例Test_method_2
上引用t
,所以Python会自动为您处理self
参数,就像处理所有方法一样。
@
后面的任何内容只是一个表达式。所以如果你使用语法:
@t.Test_method_2(a, b, c, d, e=f, g=h)
然后Test_method_2()
应该返回一个装饰器函数。一个额外级别的范围嵌套应该这样做:
def Test_method_2(self, *args, **kw):
def decorator(func):
@functools.wraps(func)
def wrapper(*wrapperargs, **wrapperkw):
fargs = args + wrapperargs
fkw = dict(kw)
fkw.update(wrapperkw)
return func(*fargs, **fkw)
return wrapper
return decorator
解构这个:
@t.Test_method_2(5, 6, 7, 8, baz='spam', ham='eggs')
def simple_function(x, y, z, n=m):
print 'this is a simple_function'
@
之后的部分,t.Test_method_2(5, 6, 7, 8, baz='spam', ham='eggs')
返回嵌套函数decorator
:
@decorator
def simple_function(x, y, z, n=m):
print 'this is a simple_function'
然后哪个python变成:
simple_function = decorator(simple_function)
和decorator(func)
返回wrapper(*wrapperargs, **wrapperkw)
。
调用simple_function(1, 2, foo='bar')
会调用wrapper(1, 2, foo='bar')
来调用原始 simple_function()
并传递fargs = [5, 6, 7, 8, 1, 2]
和fkw = {'baz': 'spam', 'ham': 'eggs', 'foo': 'bar'}
作为位置和关键字参数。
您在链接问题中看到的类装饰器模式以类似的方式工作; @
之后的表达式返回被调用的东西;而不是嵌套函数,而是创建一个类实例。这只是存储装饰器使用状态的两种不同方法。
嵌套函数的编写要小一些,而使用类可以提供比嵌套范围更多的内省选项。