繁体   English   中英

修改函数的字符串 repr 以在 dict 键中使用

[英]Modify string repr of functions for use in dict keys

是否可以并建议修改 python function 的字符串表示形式和交互使用的参数?

用例是将函数用作 dict 键,因为函数是可散列的。 例如:

def addn(n):
    return lambda x: x+n

然后可以定义键:

{addn(1): 'foo', addn(2): 'bar'}

然后在计算上使用密钥:

{k(10):v for k,v in {addn(1): 'foo', addn(2): 'bar'}.items()}

>> {11: 'foo', 12: 'bar'}

在交互式笔记本中,最好将 'addn(1)' 等视为字符串,而不是:

{<function __main__.addn.<locals>.<lambda>(x)>: 'some-json',
 <function __main__.addn.<locals>.<lambda>(x)>: 'more-json'}

**编辑:更改值以指示感兴趣的典型值通常是复杂数据 - 以前我有“foo”和“bar”。 我可能会混淆一些,值与键无关——这不是反模式,它是数据科学中具有复杂键的常见模式——frozendict 键的泛化。

这可以用装饰器完成,而不定义派生 function class 并且不引入不良后果吗?

请注意,显示参数以及 function 名称至关重要,因为这些是感兴趣的数据。

我很确定你需要使用 class 来包装这个

注意我只是在回答这个问题....我认为这不是一个好主意

进口检验

class BaseX:
    NO_RESULT = object()
    def __call__(self,*args,**kwargs):
        if self.result is not BaseX.NO_RESULT and callable(self.result):
            return self.result(*args,**kwargs)
        return BaseX(self.fn,args,kwargs)
    def __init__(self,fn,args=None,kwargs=None):
        self.called_with = None
        self.result = BaseX.NO_RESULT
        if args is not None and kwargs is not None:
            self.result = fn(*args,**kwargs)
            msg = "("
            if args:
                msg += ", ".join(map(str,args))
            if kwargs:
                msg += ", " + ", ".join(f"{k}={v!r}" for k,v in kwargs.items())
            msg += f")"
            self.called_with = msg

        self.fn = fn
        self.args = inspect.signature(fn)

    def __str__(self):
        return self.fn.__name__ + (self.called_with if self.called_with else str(self.args))
    def __repr__(self):
        return str(self)
    def __hash__(self):
        return hash(str(self))

@BaseX
def addn(n):
    return lambda x: x+n

a1 = {addn(1): 'foo', addn(2): 'bar'}
print("A1:",a1)
a2 = {k(10):v for k,v in {addn(1): 'foo', addn(2): 'bar'}.items()}
print(a2)

仍然不确定我是否理解目的并认为这是 XY 问题,但在这个例子中(仍然不是 100% 你问的):

from functools import partial

def addn(n):
    return lambda x: x+n

spam = {partial(addn, 1):'foo', partial(addn, 2):'bar'}
print(spam)
print({k()(10):v for k, v in spam.items()})

output

{functools.partial(<function addn at 0x7f34703b01e0>, 1): 'foo', functools.partial(<function addn at 0x7f34703b01e0>, 2): 'bar'}
{11: 'foo', 12: 'bar'}

甚至更好

from functools import partial

def addn(n, x):
    return x+n

spam = {partial(addn, 1):'foo', partial(addn, 2):'bar'}
print(spam)
print({k(10):v for k, v in spam.items()})

编辑,进一步思考,另一种方式(我用 2 个参数将其复杂化)

def addn(n, m):
    return lambda x: (x+n)*m

spam = {(addn(1, 2), 1, 2):'foo', (addn(2, 2), 2, 2):'bar'}
print(spam)
print({func(10):v for (func, *_), v in spam.items()})

output

{(<function addn.<locals>.<lambda> at 0x7f644e52a268>, 1, 2): 'foo', (<function addn.<locals>.<lambda> at 0x7f644ce44488>, 2, 2): 'bar'}
{22: 'foo', 24: 'bar'}

不是很好,又快又脏,但 function 和参数仍然很清楚。 当然,您始终可以按照 jonrsharpe 的建议定义自己的 class

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM