Python-如何为基于类的装饰器指定可选参数?
我怎样才能写出这样一个装潢师呢。我希望在调用decorator时能够指定max_hits的值(或者可以选择不使用它) 例如,预期用途为:Python-如何为基于类的装饰器指定可选参数?,python,decorator,memoization,Python,Decorator,Memoization,我怎样才能写出这样一个装潢师呢。我希望在调用decorator时能够指定max_hits的值(或者可以选择不使用它) 例如,预期用途为: @memoize(max_hits=7) def a(val): print val 或 (使用第一个示例会给出一个关于不正确参数的错误。) 装饰师: class memoize: """A decorator to cache previosly seen function inputs. usage: @memo
@memoize(max_hits=7)
def a(val):
print val
或
(使用第一个示例会给出一个关于不正确参数的错误。)
装饰师:
class memoize:
"""A decorator to cache previosly seen function inputs.
usage:
@memoize
def some_func(..
"""
def __init__(self, function, max_hits=None):
self.max_hits = max_hits
self.function = function
self.memoized = {}
def __call__(self, *args, **kwargs):
key = (args,tuple(kwargs.items()))
try:
return self.memoized[key]
except KeyError:
self.memoized[key] = self.function(*args,**kwargs)
return self.memoized[key]
您必须使
memoize
成为一个函数,该函数接受一个可选参数max_hits
,并返回一个decorator(即另一个将函数作为第一个参数的可调用对象);在这种情况下,可以使用以下两种语法:
@memoize()
def func(x):
[...]
@memoize(max_hits=7)
def func(x):
[...]
所以,大概是这样的:
def memoize(max_hits=None):
"""Returns a decorator to cache previosly seen function inputs.
usage:
@memoize()
def some_func(..
"""
class decorator:
def __init__(self, function):
self.max_hits = max_hits
self.function = function
self.memoized = {}
def __call__(self, *args, **kwargs):
key = (args,tuple(kwargs.items()))
try:
return self.memoized[key]
except KeyError:
self.memoized[key] = self.function(*args,**kwargs)
return self.memoized[key]
return decorator
请注意,@memoize()
将起作用,但您最初想要的@memoize
语法将不起作用;在后一种情况下,您用@memoize
修饰的函数将作为第一个参数传递给memoize
(max\u hits
)。如果要处理此情况,可以按如下方式扩展memoize
:
def memoize(max_hits=None):
if callable(max_hits):
# For sake of readability...
func = max_hits
decorator = memoize(max_hits=None)
return decorator(func)
[...original implementation follows here...]
如果您使用的是3.2+,不要自己编写,请使用functools import lru缓存中的
如果您希望支持无括号版本,那么最好为函数参数使用sentinel值,而不是反省“错误”参数。即:
class Memoized(object):
# As per the memoize definition in the question
# Leave out the "*, " in 2.x, since keyword-only arguments are only in 3.x
from functools import partial
_sentinel = object()
def memoize(_f=_sentinel, *, max_hits=None):
if _f is _sentinel:
return partial(Memoized, max_hits=max_hits)
return Memoized(_f, max_hits=max_hits)
那么我的装饰师会把课还给我吗?是的;请看我上面的扩展示例。为什么每个人都拼写它memoize。@雅各布·鲍耶:如果你要否决某件事,礼貌地说为什么。这里描述的sentinel技术是允许单个函数同时充当装饰器工厂(
@memoize(max_hits=7)
或@memoize()
)和装饰器(@memoize
)的最健壮的方法。非常感谢!很好的解决方案,效果很好-我很感激。
class Memoized(object):
# As per the memoize definition in the question
# Leave out the "*, " in 2.x, since keyword-only arguments are only in 3.x
from functools import partial
_sentinel = object()
def memoize(_f=_sentinel, *, max_hits=None):
if _f is _sentinel:
return partial(Memoized, max_hits=max_hits)
return Memoized(_f, max_hits=max_hits)