我想制作一个可以使用或不使用参数的装饰器:这样的东西:
class d(object):
def __init__(self,msg='my default message'):
self.msg = msg
def __call__(self,fn):
def newfn():
print self.msg
return fn()
return newfn
@d('This is working')
def hello():
print 'hello world !'
@d
def too_bad():
print 'does not work'
Run Code Online (Sandbox Code Playgroud)
在我的代码中,只使用带参数的装饰器工作:如何继续工作(有和没有参数)?
Eri*_*ric 41
我找到了一个例子,你可以使用@trace
或@trace('msg1','msg2')
:好!
def trace(*args):
def _trace(func):
def wrapper(*args, **kwargs):
print enter_string
func(*args, **kwargs)
print exit_string
return wrapper
if len(args) == 1 and callable(args[0]):
# No arguments, this is the decorator
# Set default values for the arguments
enter_string = 'entering'
exit_string = 'exiting'
return _trace(args[0])
else:
# This is just returning the decorator
enter_string, exit_string = args
return _trace
Run Code Online (Sandbox Code Playgroud)
Gle*_*ard 22
如果要将参数带到装饰器,则需要始终将其称为函数:
@d()
def func():
pass
Run Code Online (Sandbox Code Playgroud)
否则,您需要尝试检测参数的差异 - 换句话说,您需要神奇地猜测调用者的含义.不要创建需要猜测的API; 始终如一地说出你的意思.
换句话说,函数应该是装饰器或装饰器工厂; 它不应该是两者兼而有之.
请注意,如果您只想存储一个值,则无需编写类.
def d(msg='my default message'):
def decorator(func):
def newfn():
print msg
return func()
return newfn
return decorator
@d('This is working')
def hello():
print 'hello world !'
@d()
def hello2():
print 'also hello world'
Run Code Online (Sandbox Code Playgroud)
ric*_*rdo 13
如果你不介意依赖于使用命名参数,我做了类似于你需要的东西:
def cached_property(method=None, get_attribute=lambda a: '_%s_cached' % (a,)):
"""
Caches an object's attribute.
Can be used in the following forms:
@cached_property
@cached_property()
@cached_property(get_attribute=lambda x: 'bla')
@param method: the method to memoizes
@param get_attribute: a callable that should return the cached attribute
@return a cached method
"""
def decorator(method):
def wrap(self):
private_attribute = get_attribute(method.__name__)
try:
return getattr(self, private_attribute)
except AttributeError:
setattr(self, private_attribute, method(self))
return getattr(self, private_attribute)
return property(wrap)
if method:
# This was an actual decorator call, ex: @cached_property
return decorator(method)
else:
# This is a factory call, ex: @cached_property()
return decorator
Run Code Online (Sandbox Code Playgroud)
这是因为只有一个非关键字参数,所装饰的函数被传递给装饰器.
请注意,我还使用了传递给修饰函数的参数,在本例中为'self'.
这会起作用。
def d(arg):
if callable(arg):
def newfn():
print 'my default message'
return arg()
return newfn
else:
def d2(fn):
def newfn():
print arg
return fn()
return newfn
return d2
@d('This is working')
def hello():
print 'hello world !'
@d
def hello2():
print 'hello2 world !'
@d('Applying it twice')
@d('Would also work')
def hello3():
print 'hello3 world !'
hello()
hello2()
hello3()
# output
#
# This is working
# hello world !
# my default message
# hello2 world !
# Applying it twice
# Would also work
# hello3 world !
Run Code Online (Sandbox Code Playgroud)
如果装饰器函数@invocation没有传递任何显式参数,则使用下面的函数来调用它 def
。如果被传递的参数,那么它首先调用它们,然后的结果是初步的调用(必须本身也成为一个可调用)被调用所定义的功能。无论哪种方式,最后一次调用或唯一调用的返回值都将绑定到定义的函数名称。
归档时间: |
|
查看次数: |
21757 次 |
最近记录: |