在Codewars.com上,我遇到了以下任务:
创建一个函数add,该函数在连续调用时将数字加在一起。所以add(1)应该返回1,add(1)(2)应该返回1+2,…
add
add(1)
1
add(1)(2)
1+2
虽然我熟悉Python的基础知识,但从未遇到过可以连续调用的函数f(x),即可以称为的函数f(x)(y)(z)...。到目前为止,我什至不确定如何解释这种表示法。
f(x)
f(x)(y)(z)...
作为一个数学家,我怀疑f(x)(y)是分配到每个功能x的函数g_{x},然后返回g_{x}(y),同样也f(x)(y)(z)。
f(x)(y)
x
g_{x}
g_{x}(y)
f(x)(y)(z)
如果这种解释是正确的,Python将允许我动态创建对我来说非常有趣的函数。我在过去一个小时内一直在网上搜索,但找不到正确方向的线索。但是,由于我不知道如何调用此编程概念,所以这可能并不奇怪。
您如何称呼这个概念?在哪里可以阅读更多有关它的信息?
我不知道 函数 链接和 可调用 链接是否一样多,但是,由于函数 是 可调用的,所以我猜没有什么坏处。无论哪种方式,我都可以通过两种方式来考虑:
int
__call__
第一种方法是使用一个定义了int子类的自定义子类,__call__该子类返回具有更新后值的自身新实例:
class CustomInt(int): def __call__(self, v): return CustomInt(self + v)
add现在可以定义函数以返回CustomInt实例,该实例作为可返回自身的更新值的可调用对象,可以依次调用:
CustomInt
>>> def add(v): ... return CustomInt(v) >>> add(1) 1 >>> add(1)(2) 3 >>> add(1)(2)(3)(44) # and so on.. 50
另外,作为int子类,返回值保留的__repr__和__str__行为int。 但是,对于更复杂的操作,应适当定义其他标记 。
__repr__
__str__
正如@Caridorc在评论中指出的,add也可以简单地写成:
add = CustomInt
将类重命名为add代替CustomInt也可以类似地工作。
我能想到的唯一其他方法涉及一个嵌套函数,该函数需要一个额外的空参数调用才能返回结果。我 没有 使用nonlocal并选择将属性附加到函数对象,以使其在Python之间可移植:
nonlocal
def add(v): def _inner_adder(val=None): """ if val is None we return _inner_adder.v else we increment and return ourselves """ if val is None: return _inner_adder.v _inner_adder.v += val return _inner_adder _inner_adder.v = v # save value return _inner_adder
这将连续返回自身(_inner_adder),如果val提供了a,则将其递增(_inner_adder += val),否则,将按原样返回值。就像我提到的,它需要额外的()调用才能返回增加的值:
_inner_adder
val
_inner_adder += val
()
>>> add(1)(2)() 3 >>> add(1)(2)(3)() # and so on.. 6