Python中的函数链接 [英] Function chaining in Python

查看:112
本文介绍了Python中的函数链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在codewars.com上,我遇到了以下任务:


创建一个函数 add add(1)应该返回 1 add(1)(2) code>应返回 1 + 2 ,...


虽然我熟悉Python的基础知识,但我从来没有遇到过能够在这种继承中被调用的函数,即函数 f(x),它可以被称为 f(x)(y)(z)... 。到目前为止,我甚至不知道如何解释这个符号。



作为一名数学家,我怀疑 f(x)(y)是一个函数,每一个 x 一个函数 g_ {x} ,然后返回 g_ {x} ,同样对于 f(x)(y)(z)

如果这个解释是正确的,那么Python将允许我动态创建对我来说很有趣的函数。我在过去的一个小时内搜索了网页,但无法找到正确的方向。因为我不知道如何调用这个编程概念,所以这可能不会太令人惊讶。

你怎么称呼这个概念,我在哪里可以阅读更多关于它是什么?

解决方案

我不知道这是 function 链是否与 callable 链接,但是,因为函数是可调用的,所以我认为没有任何伤害。无论哪种方式,我可以想到这样做的两种方式:

子分类 int 并定义



第一种方法是使用自定义 int 子类定义 __ call __ 使用更新后的值返回自己的新实例:

  class CustomInt(int):
def __call __(self,v):
返回CustomInt(self + v)

函数<$现在可以定义c $ c> add 来返回一个 CustomInt 实例,该实例作为返回自身更新值的可调用对象,可以

 >>> def add(v):
... return CustomInt(v)
>>> add(1)
1
>>> add(1)(2)
3
>>>添加(1)(2)(3)(44)#等等。
50

另外,作为 int 子类,返回值保留 __ repr __ __str __ int s的行为。 尽管对于更复杂的操作,你应该适当地定义其他dunders

正如@Caridorc在评论中指出的那样, add 也可以简写为:

  add = CustomInt 

将类重命名为添加而不是 CustomInt 同样适用。





定义一个闭包,需要额外的调用才能产生值:



嵌套函数需要额外的空参数调用才能返回结果。我 not 使用 nonlocal ,并选择将属性附加到函数对象以使它在Pythons之间可移植:

  def add(v):
def _inner_adder(val = None):

如果val是None,返回_inner_adder.v
else我们增加并返回自己

如果val是None:
return _inner_adder.v
_inner_adder.v + = val
return _inner_adder
_inner_adder.v = v#保存值
返回_inner_adder

如果提供了 val ,它会不断返回自身( _inner_adder ),它会增加它( _inner_adder + = val ),如果没有,按照原样返回值。就像我提到的那样,它需要额外的()调用才能返回递增的值:

 >>> add(1)(2)()
3
>>>添加(1)(2)(3)()#等等。
6


On codewars.com I encountered the following task:

Create a function add that adds numbers together when called in succession. So add(1) should return 1, add(1)(2) should return 1+2, ...

While I'm familiar with the basics of Python, I've never encountered a function that is able to be called in such succession, i.e. a function f(x) that can be called as f(x)(y)(z).... Thus far, I'm not even sure how to interpret this notation.

As a mathematician, I'd suspect that f(x)(y) is a function that assigns to every x a function g_{x} and then returns g_{x}(y) and likewise for f(x)(y)(z).

Should this interpretation be correct, Python would allow me to dynamically create functions which seems very interesting to me. I've searched the web for the past hour, but wasn't able to find a lead in the right direction. Since I don't know how this programming concept is called, however, this may not be too surprising.

How do you call this concept and where can I read more about it?

解决方案

I don't know whether this is function chaining as much as it's callable chaining, but, since functions are callables I guess there's no harm done. Either way, there's two ways I can think of doing this:

Sub-classing int and defining __call__:

The first way would be with a custom int subclass that defines __call__ which returns a new instance of itself with the updated value:

class CustomInt(int):
    def __call__(self, v):
        return CustomInt(self + v)

Function add can now be defined to return a CustomInt instance, which, as a callable that returns an updated value of itself, can be called in succession:

>>> def add(v):
...    return CustomInt(v)
>>> add(1)
1
>>> add(1)(2)
3
>>> add(1)(2)(3)(44)  # and so on..
50

In addition, as an int subclass, the returned value retains the __repr__ and __str__ behavior of ints. For more complex operations though, you should define other dunders appropriately.

As @Caridorc noted in a comment, add could also be simply written as:

add = CustomInt 

Renaming the class to add instead of CustomInt also works similarly.


Define a closure, requires extra call to yield value:

The only other way I can think of involves a nested function that requires an extra empty argument call in order to return the result. I'm not using nonlocal and opt for attaching attributes to the function objects to make it portable between Pythons:

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 

This continuously returns itself (_inner_adder) which, if a val is supplied, increments it (_inner_adder += val) and if not, returns the value as it is. Like I mentioned, it requires an extra () call in order to return the incremented value:

>>> add(1)(2)()
3
>>> add(1)(2)(3)()  # and so on..
6

这篇关于Python中的函数链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆