[英]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.