2010-12-07 36 views
2

我需要爲任意數量的峯值創建一個函數,以傳遞給最小二乘擬合例程。對於每一個峯存在於50次返回的函數的函數的額外項,即Python中的動態函數構建

一個術語具有值:f(p, x) = p[0]*50 + p[1]*60*x

:在50,60返回的函數f(p, x) = p[0]*50

兩個方面與值三個方面與值在50,60,70返回:f(p, x) = p[0]*50 + p[1]*60*x + p[2]*70*x^2

幾個幼稚嘗試如下所示,

def foo(vals): 
    fn = lambda p, x: 0 
    i = 0 
    for v in vals: 
     fn = lambda p, x : fn(p, x) + p[i] * v * x**i 
     i += 1 
    return fn 
# Causes a recursion error (I think)

第二次嘗試......

def bar(vals): 
    terms = [] 
    i = 0 
    for v in vals: 
     terms.append(lambda x, p: p[i] * v * x**i) 
     i += 1 
    def fn(x, p): 
     tvals = [t(x, p) for t in terms] 
     sum = 0 
     for t in terms: 
      sum = sum + t(x, p) 
     return sum 
    return fn 
# Generates the wrong values 

我懷疑這是引用一個問題,即Python將參照表聲明等,但是這是一個有點複雜解開 - 任何幫助,將不勝感激!

+0

你能提供一個測試用例,顯示你期待得到什麼(和你在第二種情況中得到什麼)? – NPE 2010-12-07 13:17:03

+0

是的,有點難以猜到你想要什麼,特別是因爲第一次只是覆蓋`fn`多... – 2010-12-07 13:22:21

+0

嗯,它似乎在我試圖調試時複製代碼的第二次嘗試時,它不應該返回一個列表,它應該返回該列表的總和......並且我更好地解釋了期望的結果 – Brendan 2010-12-07 14:18:22

回答

2

如何:

def foo(vals): 
    def f(p,x): 
     result=0 
     for i,(av,ap) in enumerate(zip(vals,p)): 
      result+=av*ap*(x**i) 
     return result 
    return f 

print(foo([50])([2],3)) 
# f(p,x)=50*2 
# 100 
print(foo([50,60])([2,3],4)) 
# f(p,x)=50*2+60*3*x 
# 820 
0

一個簡單的修改存儲在默認參數,每個fn參考

def foo(vals): 
    fn = lambda p, x: 0 
    i = 0 
    for v in vals: 
     fn = lambda p, x, f=fn, i=i: f(p, x) + p[i] * v * x**i 
     i += 1 
    return fn 
+0

啊,這似乎給了'列表索引超出範圍'的錯誤? – Brendan 2010-12-07 14:45:48

+0

@Brendan,是啊,需要在`i`上關閉。 – 2010-12-07 20:54:45

1

瓶蓋不要在他們的創作時間捕捉在外部範圍變量的值,他們真正抓住這些變量。 [lambda: i for i in range(5)]給你五個函數,全部返回4,因爲它們都指向相同的i(迭代結束時爲4)。您可以使用默認參數(在函數定義時綁定值)來解決此問題:[lambda i=i: i for i in range(5)]按預期工作。

另外,使用enumerate。這一點,加上製作fn拉姆達可以降低代碼到只有兩個,伊莫同樣可讀,線(我假設的第二個版本,第一個打破似乎在很多方面,如在評論中所示):

def bar(vals): 
    terms = [lambda x, p, i=i, v=v: p[i] * v * x**i for i, v in enumerate(vals)] 
    return lambda x, p: sum(term(x, p) for term in terms) 
1

你可以寫整個事情作爲一個返回閉包功能:

def make_function(vals): 
    def evaluate(x,p): 
     return sum(p[i] * v * x**i 
        for i,v in enumerate(vals)) 
    return evaluate 

你正在運行與terms功能的問題經常出現。我之前寫了一個長的解釋about this problem,希望它會有幫助。

順便說一句,foobar句法變量,這意味着它們被用於解釋語法。對於實現問題,您應該真正使用在域中有用的好名稱,這通常會使問題更容易理解。