1

这个问题与我的代码无关,我
只想说明我需要惰性评估的原因function.func_name


curry在我的代码中使用了一个装饰器我
通过修改 func_name 来显示咖喱参数
所以当我需要一些调试时,我可以很容易地找出哪些参数已经被咖喱

>> 我的修改版<<
>> 原版<<

我的例子curry

@curry
def f(a, b, c, flag_foo=True, flag_bar=False):
    pass

>>> f
<function f at 0x100545398>

>>> f(1, flag_bar=True)
<function f(1, flag_bar=True) at 0x1005451b8>

>>> f(1, flag_bar=True)(3, flag_foo=False)
<function f(1, 3, flag_foo=False, flag_bar=True) at 0x1004aee60>

由于func_name将永远不会在没有调试的情况下访问,
我想避免评估 func_name 的开销

但是,function最终类是不能被子类化的吗?
有什么方法可以执行惰性求值function.func_name吗?

欢迎任何建议

4

1 回答 1

1

编码:

class Curried(object):
    def __init__(self, func, args=None, kwargs=None):
        self._func = func
        self._args = () if args is None else args[:]
        self._kwargs = {} if kwargs is None else dict(kwargs)
        self._name = None

    def __call__(self, *args, **kwargs):
        if args or kwargs:
            return Curried(self._func,
                           self._args + args,
                           dict(self._kwargs.items() + kwargs.items()))
        else:
            return self._func(*self._args, **self._kwargs)

    def __str__(self):
        if self._name is None:
            self._name = self._get_curried_name()
        return self._name

    def _get_curried_name(self):
        _args = ([str(a) for a in self._args] +
                 ['{}={}'.format(k, v) for k, v in self._kwargs.iteritems()])
        all_args = ", ".join(_args)
        return '<curried {}({}) at 0x{:x}>'.format(
            self._func.func_name, all_args, id(self))

    def curry(func):
        _curried = Curried(func)
        return _curried

测试:

@curry
def f(a, b, c, flag_foo=True, flag_bar=False):
    return 'horray!'

print f
print f(1, 2, flag_bar=True)
print f(1, 2, flag_bar=True)(3, flag_foo=False)
print f(1, 2, flag_bar=True)(3, flag_foo=False)()

结果:

<curried f() at 0x100484210>
<curried f(1, 2, flag_bar=True) at 0x100484250>
<curried f(1, 2, 3, flag_bar=True, flag_foo=False) at 0x100484310>
horray!

而不是一个“纯”函数,在这里你得到一个作为函数的可调用类。您只评估一次名称。当然,如果你愿意,func_name你可以添加这样的变量property并返回str(self),它会被评估一次

于 2013-05-01T17:04:40.267 回答