有没有一种更像Python的方法来做以下事情:
def mysteryFunction( it, fun, val ):
out = []
for x in it:
y,val = fun(x,val)
out.append(y)
return out,val
其中it
是iterable,fun
是一个接受两个输入并返回两个输出的函数,val
是一个初始值,它通过每次调用fun
进行“转换”?你知道吗
我之所以问这个问题是因为我经常使用map, zip, filter, reduce
和列表理解,但是我不能将前面的函数表示为这些函数的组合,现在已经出现了好几次了。是我遗漏了一个隐藏的习语,还是这个习语太过利基而配不上一个?你知道吗
一个具体的例子是从一定的秒数开始计算(年、周、日、时、分、秒)的持续时间:
fac = (365*24*3600, 7*24*3600, 24*3600, 3600, 60, 1)
dur,rem = mysteryFunction( fac, lambda x,y: divmod(y,x), 234567 )
其中dur
是持续时间元组,rem
对应于最后的余数(此处为零或十进制,具体取决于初始值的类型)。这不仅仅是精心挑选的,还有许多其他的例子,例如:积分微分方程的固定步长方法(迭代步长、步进函数、初始状态);模拟有界随机游走;无递归的跨深度树处理;等等
这种结构类似于the ^{} generator function 的设计目的。例如,您的函数可能与以下函数一起使用:
然后打电话给:
它将返回:
从0到4的累计和,以及最终的和。你知道吗
itertools.accumulate
可以做同样的事情,但它是懒惰的(它根据请求返回每个累积值),并且只对单个输出函数的两个操作数起作用;对于这种情况,它最终变得更简单:将产生与
mystery_function
相同的list
(第二个结果只是list
的最后一个值),但是您也可以延迟使用它,而不将结果存储在list
中,例如:您可能会通过
accumulate
来处理双输入双输出函数(或者更准确地说,从accumulate
输出的值中丢弃您不关心的值),但大多数情况下,我希望第二个输出是迄今为止的累积值,而不是真正分开的,因此避免第二个输出会更干净。你知道吗为了好玩,一种可怕的按摩你的结构来匹配
accumulate
。假设您想向输入中的每个元素添加一个base
值,但是每次将base
减少1。对于函数,您将执行(对于10的初始值base
):它(由于传递了
range
,抵消了base
的每次减少)产生了([10, 10, 10, 10, 10], 5)
。与accumulate
类似的代码可能是:然后(因为不能直接为
accumulate
指定初始值,所以有些丑陋):这使得
vals
变成了(10, 10, 10, 10, 10)
,base
变成了5
,就像在你的代码中一样(为这个魔术道歉;zip
使用通用的嵌套解包,既漂亮又恐怖)。你知道吗相关问题 更多 >
编程相关推荐