Python 如何链接多个参数?i、 e.加上(1)(2)(3)=6

Python 如何链接多个参数?i、 e.加上(1)(2)(3)=6,python,Python,我正在尝试创建一个函数,它将多个参数的结果链接起来 def hi(string): print(string)<p> return hi def hi(字符串): 打印(字符串) 回电 调用hi(“Hello”)(“World”)可以正常工作,并成为Hello\n World 问题是当我想将结果附加为单个字符串时,但是 returnstring+hi产生错误,因为hi是一个函数 def hi(*args): return "\n".join(args) 我已

我正在尝试创建一个函数,它将多个参数的结果链接起来

def hi(string):
   print(string)<p>
   return hi
def hi(字符串):
打印(字符串)
回电
调用
hi(“Hello”)(“World”)
可以正常工作,并成为
Hello\n World

问题是当我想将结果附加为单个字符串时,但是
returnstring+hi
产生错误,因为
hi
是一个函数

def hi(*args):
    return "\n".join(args)
我已经尝试使用
\uuu str\uuu
\uu repr\uu
来更改hi在没有输入时的行为方式。但这只会在其他地方造成不同的问题

hi(“Hello”)(“World”)=“Hello”(“World”)
->自然会产生错误


我理解程序无法解决它的原因,但我无法找到解决方案。

通过让
hi
返回对自身的引用,您正在陷入一些深刻的、哈斯克尔式的理论问题。相反,只需接受多个参数并在函数中连接它们

def hi(*args):
    return "\n".join(args)
一些示例用法:

print(hi("Hello", "World"))
print("Hello\n" + hi("World"))

您在这里遇到了困难,因为每个函数调用的结果本身都必须是可调用的(因此您可以链接另一个函数调用),同时也是合法字符串(如果您不链接另一个函数调用,只使用返回值)

幸运的是,Python已经介绍过了:通过在任何类型上定义
\uu call\uu
方法,都可以使其像函数一样可调用。像
str
这样的内置类型没有这样的方法,但是您可以定义
str
的子类

class hi(str):
    def __call__(self, string):
        return hi(self + '\n' + string)
这不是很漂亮,也有点脆弱(即,当您使用特殊字符串执行几乎任何操作时,您都会得到常规的
str
对象,除非您重写
str
的所有方法以返回
hi
实例),因此不被认为是非常Pythonic的

在这种特殊情况下,当您开始使用结果时,如果您最终得到了常规的
str
实例,则没有多大关系,因为此时您已经完成了函数调用的链接,或者应该处于任何正常状态。但是,在通过子类化向内置类型添加功能的一般情况下,这通常是一个问题

第一个近似值是,标题中的问题可以类似地回答:

class add(int):    # could also subclass float
    def __call__(self, value):
        return add(self + value)
但是,要真正做到
add()
正确,您需要能够返回结果类型的可调用子类,不管它是什么类型;它可以是
int
float
之外的东西。我们可以根据结果类型动态创建它们,而不是尝试对这些类型进行编目并手动编写必要的子类。下面是一个快速而肮脏的版本:

class AddMixIn(object):
     def __call__(self, value):
         return add(self + value)

def add(value, _classes={}):
    t = type(value)
    if t not in _classes:
        _classes[t] = type("add_" + t.__name__, (t, AddMixIn), {})
    return _classes[t](value)
令人高兴的是,这个实现对字符串很有效,因为它们可以使用
+
进行连接

一旦你开始沿着这条路走下去,你可能也会想在其他操作中这样做。这是一个拖动复制和粘贴的过程,每个操作的代码基本相同,所以让我们编写一个函数来为您编写函数!只需指定一个实际执行工作的函数,即接受两个值并对它们执行某些操作,它就会返回一个为您执行所有类搜索的函数。您可以使用lambda(匿名函数)或预定义函数指定操作,例如来自
操作符
模块的函数。因为它是一个接受函数并返回函数(好吧,是一个可调用对象)的函数,所以它也可以用作装饰器

 def chainable(operation):

     class CallMixIn(object):
         def __call__(self, value):
             return do(operation(self, value))

     def do(value, _classes={}):
         t = type(value)
         if t not in _classes:
             _classes[t] = type(t.__name__, (t, CallMixIn), {})
         return _classes[t](value)

     return do

 add = chainable(lambda a, b: a + b)

 # or...
 import operator
 add = chainable(operator.add)

 # or as a decorator...
 @chainable
 def add(a, b): return a + b
最后,它仍然不是很漂亮,仍然有点脆弱,仍然不会被认为是非常蟒蛇

如果您愿意使用一个额外的(空)调用来表示链的结束,事情会变得简单得多,因为您只需要返回函数,直到您在没有参数的情况下被调用:

def add(x):
    return lambda y=None: x if y is None else add(x+y)
你这样称呼它:

add(3)(4)(5)()    # 12

你可能想看看*args或**kwargsMihrr,欢迎来到SO。请使用“代码格式”按钮而不是代码的块引号。我不明白为什么人们对他的问题投了反对票。。。