我是编程新手,但我最近一直在尝试算法。我需要使用一个方程式进行计算,该方程式使用坐标平面中结构装配中的所有角度作为变量。装配变量,所以我需要这个函数来遍历数据,并将装配中每两个点的各个方程组合成用于计算的方程。我感到困惑的部分是如何组合这些功能。如果有这样的话,我想以几乎像“追加”的方式这样做。
假设我正在浏览数据,此时我有功能
a = lambda (x1,x2,x3,x4): (x1*x2)+(x3*x4)
以前从前两组生成,现在我想添加一个eq。来自第三组
b = lambda (x5,x6): (x5/x6)
def new_lambda(a,b):
return lambda (x1,x2,x3,x4,x5,x6): (x1*x2)+(x3*x4)+(x5/x6)
这是我想要做的一个简单的例子。除了功能创建的基础之外,我对此并不熟悉,所以这可能有点过头了。随意给我推荐一般阅读。如果需要澄清,我也可以这样做。
答案 0 :(得分:2)
我认为问题是你需要知道每个函数的arity,以便相应地分配“组合”函数的参数。
也许你可以将你的函数包装在一个类中,如下所示:
class Function:
def __init__ (self, arity, f):
self.arity = arity
self.f = f
def __call__ (self, *args):
return self.f (*args)
def __add__ (self, g):
if not isinstance (g, Function):
raise Exception ('Here be dragons')
def fg (*args):
return self.f (*args [:self.arity] ) + g.f (*args [self.arity:] )
return Function (self.arity + g.arity, fg)
a = Function (4, lambda x1, x2, x3, x4: (x1 * x2) + (x3 * x4) )
b = Function (2, lambda x1, x2: x1 / x2)
print (a (1, 2, 3, 4) )
print (b (10, 20) )
c = a + b
print (c (1, 2, 3, 4, 10, 20) )
有关检查arity的一些话。结果函数fg
只有一个参数,即*x
,其检查的arity将导致0,因此禁止添加已添加的函数。看看这里:
#Using my original class
a = Function (2, lambda x1, x2: x1 * x2)
b = Function (2, lambda x1, x2: x1 / x2)
c = a + a
print (c (1, 2, 3, 4) ) #prints 14
c = c + b
print (c (1, 2, 3, 4, 5, 6) ) #prints 14.833333333333334
现在,如果我们使用这样的检查(如果你打算再使用它,请纠正我):
import inspect
class InspectedFunction:
def __init__ (self, f):
self.f = f
def __call__ (self, *args):
return self.f (*args)
def __add__ (self, g):
if not isinstance (g, InspectedFunction):
raise Exception ('Here be dragons')
arity = len (inspect.getargspec (self.f).args)
def fg (*args):
return self.f (*args [:arity] ) + g.f (*args [arity:] )
return InspectedFunction (fg)
a = InspectedFunction (lambda x1, x2: x1 * x2)
b = InspectedFunction (lambda x1, x2: x1 / x2)
c = a + a
print (c (1, 2, 3, 4) ) #prints 14
c = c + b
print (c (1, 2, 3, 4, 5, 6) ) #inspected arity of c is 0
会这样做:
Traceback (most recent call last):
File "nomimporta.py", line 45, in <module>
print (c (1, 2, 3, 4, 5, 6) )
File "nomimporta.py", line 30, in __call__
return self.f (*args)
File "nomimporta.py", line 37, in fg
return self.f (*args [:arity] ) + g.f (*args [arity:] )
File "nomimporta.py", line 37, in fg
return self.f (*args [:arity] ) + g.f (*args [arity:] )
TypeError: <lambda>() takes exactly 2 arguments (0 given)
答案 1 :(得分:2)
我会添加另一个答案,以免超重我的第一个,因为这个包括我最初的想法和来自@martineau的有价值的输入(这次希望符合PEP-8)。
让我们定义一个这样的函数,让我们试着猜测它的优点:
import inspect
import operator
class UnguessableArityException(Exception): pass
class Function:
def __init__(self, f, arity = ...):
self.f = f
self.arity = arity
if arity == ...:
argspec = inspect.getfullargspec(f)
if argspec.varargs or argspec.kwonlyargs:
raise UnguessableArityException()
self.arity = len(argspec.args)
def __call__(self, *args):
return self.f(*args)
def op(self, g, op):
if isinstance(g, Function):
return Function(lambda *args: op(self.f(*args[:self.arity]), g.f(*args[self.arity:])), self.arity + g.arity)
return Function(lambda *args: op(self.f(*args), g), self.arity)
def rop(self, g, op):
return Function(lambda *args: op(g, self.f(*args)), self.arity)
def __add__(self, g): return self.op(g, operator.add)
def __radd__(self, g): return self.rop(g, operator.add)
def __mul__(self, g): return self.op(g, operator.mul)
def __rmul__(self, g): return self.rop(g, operator.mul)
def __truediv__(self, g): return self.op(g, operator.truediv)
def __rtruediv__(self, g): return self.rop(g, operator.truediv)
现在我们基本上只需要定义身份:
#define identity
i = Function(lambda x: x) # λx.x
使用该身份,您可以开始构建“增长”(“追加”)功能。
#now you can start building your function
f = i * i # λxy.x*y
print(f(3, 2))
#later in your code you need to "append" another term λxy.x*y
f = f + f # λxyza.x*y+z*a
print(f(3,2,1,4))
#even later, you need to "append" a term λxy.x/y
f = f + i / i # λxyzabc.x*y+z*a+b/c
print(f(3,2,1,4,14,2))
#works also with constants
f = 2 * f # λxyzabc.2*(x*y+z*a+b/c)
print(f(3,2,1,4,14,2))
答案 2 :(得分:1)