我有两个函数,f
和g
。它们都具有相同的签名:(x)
。我想创建一个新函数z
,具有相同的签名:
def z(x):
return f(x) * g(x)
除此之外,我希望能够编写 z = f * g
代码,而非以上的代码。这种方式可行吗?
我有两个函数,f
和g
。它们都具有相同的签名:(x)
。我想创建一个新函数z
,具有相同的签名:
def z(x):
return f(x) * g(x)
除此之外,我希望能够编写 z = f * g
代码,而非以上的代码。这种方式可行吗?
有类似的实现是可能的:is
z = lambda x: f(x) * g(x)
个人而言,我认为这种方法比 z = f * g
更直观,因为在数学上,函数相乘没有意义。基于 *
操作符的解释,它可能表示复合,即 z(x) = f(g(x))
,但绝不是调用结果的乘积。另一方面,上述的 lambda
很明确,写起来只需要多写一点字符。
更新:感谢 JBernardo 的努力。我原本想象这会更加难搞,结果还没有那么麻烦。不过,我建议不要在真实的代码中使用这种方式。
f * g
看起来有歧义,所以我宁愿使用lambda。 - max__name__
属性——这也不会有太大损失。 - jsbuenofrom 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
FuncOperations
中定义所需的所有操作符,使用元类有什么优势呢?(我在这里发布了一些示例代码:http://stackoverflow.com/questions/13839288/higher-order-functions-automatic-generation-vs-manual-definition) - max使用装饰器可以按照你期望的语法完成 (虽然使用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
def y():
return 3
z = x * y
z()