两个函数的乘积

4

我有两个函数,fg。它们都具有相同的签名:(x)。我想创建一个新函数z,具有相同的签名:

def z(x):
  return f(x) * g(x)

除此之外,我希望能够编写 z = f * g 代码,而非以上的代码。这种方式可行吗?


不可能 - 函数参数没有定义运算符。 - mathematical.coffee
3个回答

10

有类似的实现是可能的:is

z = lambda x: f(x) * g(x)

个人而言,我认为这种方法比 z = f * g 更直观,因为在数学上,函数相乘没有意义。基于 * 操作符的解释,它可能表示复合,即 z(x) = f(g(x)),但绝不是调用结果的乘积。另一方面,上述的 lambda 很明确,写起来只需要多写一点字符。


更新:感谢 JBernardo 的努力。我原本想象这会更加难搞,结果还没有那么麻烦。不过,我建议不要在真实的代码中使用这种方式。


啊,是的,当然。我同意 f * g 看起来有歧义,所以我宁愿使用lambda。 - max
不确定在这种情况下lambda是否好用。并不是说我的答案没有使用它,而只是想证明它是可行的。对于你的情况,你将失去函数名称(z)而得不到任何好处。我认为使用“def”声明会更好。 - JBernardo
@JBernardo:为什么要“放弃函数名”?该函数归属于名称z,就像是def'ef一样。除非您指的是内部的__name__属性——这也不会有太大损失。 - jsbueno

8
有趣的是,这是完全可能的。几天前我做了一个项目来完成这样的事情。
这是它的链接:FuncBuilder 目前,您只能定义变量,但是您可以使用我的元类和其他一些函数来构建您想要的类。
问题:
  • 速度慢
  • 真的很慢
  • 您认为您想要这个,但按照函数的本意描述函数是正确的方法。
您应该使用您的第一个代码。
仅作为概念验证:
from funcbuilder import OperatorMachinery

class FuncOperations(metaclass=OperatorMachinery):
     def __init__(self, function):
          self.func = function
     def __call__(self, *args, **kwargs):
          return self.func(*args, **kwargs)

def func(self, *n, oper=None):
    if not n:
        return type(self)(lambda x: oper(self.func(x)))
    return type(self)(lambda x: oper(self.func(x), n[0](x)))

FuncOperations.apply_operators([func, func])

现在你可以像这样编写代码:

@FuncOperations
def f(x):
    return x + 1

@FuncOperations
def g(x):
    return x + 2

期望的行为是:

>>> z = f * g
>>> z(3)
20

我在FuncBuilder项目中添加了更好的版本。它可用于FuncOperation对象和其他可调用对象之间的任何操作。也适用于一元操作。 :D

你可以尝试使用它来创建像这样的函数:

z = -f + g * h

我开始拼凑一个类来证明它可以很容易地完成,但这更加优雅,非常好 :) - dabhaid
我在我的项目中使用了你的想法,目前它运行得非常好。虽然我没有使用元类。相对于在FuncOperations中定义所需的所有操作符,使用元类有什么优势呢?(我在这里发布了一些示例代码:http://stackoverflow.com/questions/13839288/higher-order-functions-automatic-generation-vs-manual-definition) - max
@max 我喜欢元类,因为稍后扩展代码不需要太多工作(就像我上面所做的为函数创建新行为一样)。但是如果你已经习惯了其他方法,请随意使用,因为在开始时创建元类可能有点困难。 - JBernardo

3

使用装饰器可以按照你期望的语法完成 (虽然使用lambda可能更好)。正如所述,函数没有为它们定义运算符,但是在Python中可以使对象像函数一样被调用 -- 因此下面的装饰器只需将函数包装在一个对象中,该对象的乘法针对另一个函数进行了定义:

class multipliable(object):
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kw):
        return self.func(*args, **kw)
    def __mul__(self, other):
        @multipliable
        def new_func(*args, **kw):
            return self.func(*args, **kw) * other(*args, **kw)
        return new_func

@multipliable
def x():
    return 2

(在 Python 2 和 Python 3 中测试过)
def y():
    return 3

z = x * y
z()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接