是否应该添加额外的图层以支持__repr__?

kni*_*ght 3 python python-2.x

我正在研究一个主要返回闭包而不是传统的基于类的方法的Python项目.例如:

def term(token):
    def fn(text):
        return (...)
    return fn
Run Code Online (Sandbox Code Playgroud)

可以想象,调试和测试闭包是一个噩梦,特别是如果我在整个代码中使用相同的名称来封闭.例如:

>>> term('t')
<function fn at 0x...>
Run Code Online (Sandbox Code Playgroud)

所以我尝试将它包装在一个类中以__repr__从namedtuple中获取特殊处理:

def rr(cls, attrs):
    T = namedtuple(cls, attrs)

    class G(object):
        __slots__ = ()

        def __init__(self, repr_message, callable):
            self.callable = callable
            self.repr_message = repr_message

        def __call__(self, *args, **kwargs):
            return self.callable(*args, **kwargs)

        def __repr__(self):
            return self.repr_message

    K = type(cls, (G,), {})

    def wrapper(fn):
        def init(*args, **kwargs):
            t = T(*args, **kwargs)
            return K(
                repr(t),
                fn(*args, **kwargs),
            )
        return init
    return wrapper
Run Code Online (Sandbox Code Playgroud)

这样:

>>> rr('Term', ['token'])(term)('$')
Term(token='$')
Run Code Online (Sandbox Code Playgroud)

你可以想象这可能会对性能产生影响.我的问题是,如果这种包装更可取,如果更多的是Pythonic而不仅仅是返回"丑陋"的封闭?

PM *_*ing 6

更轻松的方法是简单地修改闭包的func_name属性.结果不如代码生成的结果那么漂亮,但它对RAM和性能的影响最小.

def term(token):
    def fn(text):
        return text.split(token)
    fn.func_name = "term(token={0!r})".format(token)
    return fn

s = 'splitthistestup'
f = term('t')
g = term('i')
print(f, f(s))
print(g, g(s))
Run Code Online (Sandbox Code Playgroud)

典型输出

<function term(token='t') at 0xb74878b4> ['spli', '', 'his', 'es', 'up']
<function term(token='i') at 0xb74878ec> ['spl', 'tth', 'stestup']
Run Code Online (Sandbox Code Playgroud)

对于Python 3,您需要做一些稍微不同的事情.

fn.func_name = ...
Run Code Online (Sandbox Code Playgroud)

变为:

fn.__qualname__ = ...
Run Code Online (Sandbox Code Playgroud)