是否可以使用一组参数创建一个可以__init__
'的装饰器,然后使用其他参数调用方法?
例如:
from foo import MyDecorator
bar = MyDecorator(debug=True)
@bar.myfunc(a=100)
def spam():
pass
@bar.myotherfunc(x=False)
def eggs():
pass
如果 , 可以提供一个有效的例子吗?
答案 0 :(得分:4)
您需要使用其他级别的包装,例如:
import functools
def say_when_called(what_to_say):
def decorator(fn):
@functools.wraps(fn)
def wrapper(*args, **kw):
print what_to_say
return fn(*args, **kw)
return wrapper
return decorator
@say_when_called("spam")
def my_func(v):
print v
my_func("eggs")
输出:
spam
eggs
(见http://codepad.org/uyJV56gk)
请注意,我在这里使用了functools.wraps
来使装饰函数看起来像原始函数。这不是功能上的要求,但在代码读取函数的__name__
或__doc__
属性时,这是一件好事。
基于类的示例:
class SayWhenCalledWrapper(object):
def __init__(self, fn, what_to_say):
self.fn = fn
self.what_to_say = what_to_say
def __call__(self, *args, **kw):
print self.what_to_say
return self.fn(*args, **kw)
class SayWhenCalled(object):
def __init__(self, what_to_say):
self.what_to_say = what_to_say
def __call__(self, fn):
return SayWhenCalledWrapper(fn, self.what_to_say)
@SayWhenCalled("spam")
def my_func(v):
print v
my_func("eggs")
输出:
spam
eggs
答案 1 :(得分:3)
当然,装饰器只是一个接受函数并返回函数的函数。没有理由不能将函数(或者,如果你有参数,不能返回)实例方法。这是一个非常简单的例子(因为我不确定你究竟要用这个做什么):
class MyDecorator(object):
def __init__(self, debug):
self.debug = debug
def myfunc(self, a):
def decorator(fn):
def new_fn():
if self.debug:
print a
fn()
return new_fn
return decorator
def myotherfunc(self, x):
def decorator(fn):
def new_fn():
if self.debug:
print x
fn()
return new_fn
return decorator
就像我说的那样,我无法想到这个问题的用例。但我确信他们在那里。
答案 2 :(得分:0)
property decorator有点像这样。 @property
修饰一个函数,并用一个具有getter,setter和deleter函数的对象替换它,这些函数也是装饰器。
这比OP的例子稍微复杂一点,因为有两个级别的装饰,但原理是相同的。
答案 3 :(得分:0)
class MyInnerDecorator:
def __init__( self, outer_decorator, *args, **kwargs ):
self._outerDecorator = outer_decorator
self._args = args
self._kwargs = kwargs
def __call__( self, f ):
print "Decorating function\n"
self._f = f
return self.wrap
def wrap( self, *args, **kwargs ):
print "Calling decorated function"
print "Debug is ", self._outerDecorator._debug
print "Positional args to decorator: ", self._args
print "Keyword args to decorator: ", self._kwargs
print "Positional args to function call: ", args
print "Keyword args to function call: ", kwargs
return self._f( *args, **kwargs )
print "\n"
class MyDecorator:
def __init__( self, debug ):
self._debug = debug
def myFunc( self, *args, **kwargs ):
return MyInnerDecorator( self, "Wrapped by myFunc", *args, **kwargs )
def myOtherFunc( self, *args, **kwargs ):
return MyInnerDecorator( self, "Wrapped by myOtherFunc", *args, **kwargs )
bar = MyDecorator( debug=True )
@bar.myFunc( a=100 )
def spam( *args, **kwargs ):
print "\nIn spam\n"
@bar.myOtherFunc( x=False )
def eggs( *args, **kwargs ):
print "\nIn eggs\n"
spam( "penguin" )
eggs( "lumberjack" )
哪个输出:
Decorating function
Decorating function
Calling decorated function
Debug is True
Positional args to decorator: ('Wrapped by myFunc',)
Keyword args to decorator: {'a': 100}
Positional args to function call: ('penguin',)
Keyword args to function call: {}
In spam
Calling decorated function
Debug is True
Positional args to decorator: ('Wrapped by myOtherFunc',)
Keyword args to decorator: {'x': False}
Positional args to function call: ('lumberjack',)
Keyword args to function call: {}
In eggs