2012-01-25 75 views
2

我有两个功能,fg。两者都有相同的签名:(x)。我想创建一个新的功能,z,具有相同签名:产品的两个功能

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

只是我希望能写

z = f * g,而不是上面的代码。可能吗?

+0

不要这样认为 - 运营商没有为函数参数定义。 –

回答

7

有趣的是,这是很有可能的。我前几天做了一个项目来做类似的事情。

这就是: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 
+0

我开始一起黑课,向我自己证明它可以很容易地完成,但这是更优雅,非常好:) – dabhaid

+0

我在我的项目中使用你的想法,迄今为止效果很好。尽管我没有使用元类。元类的优点与简单定义'FuncOperations'中所需的所有运算符有什么区别? (我发布了一些示例代码[这里](http://stackoverflow.com/questions/13839288/higher-order-functions-automatic-generation-vs-manual-definition)。) – max

+0

@max我喜欢元类,因为它不是很多工作以后扩展代码(就像我上面为函数创建新行为一样)。但随时可以处理你已经习惯的事情,因为在开始时创建元类可能有点困难。 – JBernardo

9

一些接近可能:

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

就个人而言,我觉得这种方式比z = f * g更加直观,因为数学,相乘功能并不意味着什么。根据*运营商的解释,它可能意味着组合所以z(x) = f(g(x)),但绝对不是乘积的调用结果。另一方面,上面的lambda非常明确,坦率地说只需要更多的字符来编写。


更新:荣誉给JBernardo黑客一起。我想象它会比结果更加黑客。仍然,我会建议不要在实际代码中使用它。

+0

啊,是的,当然。我同意'f * g'看起来不明确,所以我宁愿使用lambda。 – max

+0

不确定在这种情况下lambda是否有用。并不是说我的答案没有使用它,而只是为了证明它是可能的。在你的情况下,你只会放弃函数名称(z)而没有任何好处。我想,“def”声明还是比较好的。 – JBernardo

+0

@Jernardo:为什么“放松功能名称”?该函数归属于z,就好像它是def'ef一样。除非你的意思是内部的'__name__'属性 - 不管怎么说,这都不是什么大问题。 – jsbueno

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()