Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-如何为基于类的装饰器指定可选参数?_Python_Decorator_Memoization - Fatal编程技术网

Python-如何为基于类的装饰器指定可选参数?

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

我怎样才能写出这样一个装潢师呢。我希望在调用decorator时能够指定max_hits的值(或者可以选择不使用它)

例如,预期用途为:

@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)