2016-06-14 44 views
-1

通常,我想要做的是製作一個涉及一些函數或函數的列表,但該函數的參數將根據「i 「for循環,所以當我定義列表時,參數沒有完全定義。 想象一下func(x),我想要一個像[func(x * i),func(x * i ** 2)]這樣的列表。這意味着,將會定義一些參數x,但我想通過for循環中的「i」(迭代器)對其進行修改。 具體而言,我想要做的是構建一個二維數組的特定模式(由列表表示),將圍繞陣列的對角線。但是,模式的值取決於我所在的數組的行。所以我跟蹤我們在哪一行,並將該「我」值用作函數中的一個參數。 問題是,當我定義列表時,它試圖評估函數,並崩潰,因爲我還沒有定義(它會被定義一旦我們通過for循環) 有沒有某種方式來延遲評估列表中的函數直到它進入for循環?Python:製作一個包含函數但尚未定義參數的列表

回答

1

我懷疑你的二維數組有更好的定義對角線的方法,比迭代遍歷行和計算這樣的函數更好。而是把重點放在「拖延」功能的評價,我會試試這個問題:

定義一個簡單的函數

In [438]: def func(x): 
    .....:  return x**2 
    .....: 

因爲解釋試圖評估x*i此列表定義不起作用然後將它們傳遞給func。它將使用它現有的xi

In [442]: [func(x*i),func(x*i**2)] 
... 

NameError: name 'x' is not defined 

相反,我可以將每個函數調用包裝在另一個函數調用中。它可能是一個命名函數,或者我在這裏做一個未命名的lambda。就像的funcx*i身體被延遲,直到拉姆達被稱爲:

In [443]: [lambda x,i:func(x*i), lambda x,i: func(x*i**2)] 
Out[443]: [<function __main__.<lambda>>, <function __main__.<lambda>>] 

In [444]: flist=_ # assign that list to a new name for later use 

現在,我們可以定義一個xi,然後在列表評估功能:

In [445]: x=np.arange(3)  
In [446]: i=2 
In [447]: [f(x,i) for f in flist] 
Out[447]: [array([ 0, 4, 16]), array([ 0, 16, 64])] 

,或者我們可以換在迭代結束i

In [449]: [[f(x,i) for f in flist] for i in range(3)] 
Out[449]: 
[[array([0, 0, 0]), array([0, 0, 0])], 
[array([0, 1, 4]), array([0, 1, 4])], 
[array([ 0, 4, 16]), array([ 0, 16, 64])]] 

我甚至可以變成一個3d數組:

In [450]: np.array(_) 
Out[450]: 
array([[[ 0, 0, 0], 
     [ 0, 0, 0]], 

     [[ 0, 1, 4], 
     [ 0, 1, 4]], 

     [[ 0, 4, 16], 
     [ 0, 16, 64]]]) 

另一種方法是參數化包裝功能部件

In [451]: def func1(x,i,p=1): 
    .....:  return func(x*i**p) 

In [452]: [[func1(x,i,p) for p in [1,2]] for i in range(3)] 
Out[452]: 
[[array([0, 0, 0]), array([0, 0, 0])], 
[array([0, 1, 4]), array([0, 1, 4])], 
[array([ 0, 4, 16]), array([ 0, 16, 64])]] 

functools具有partial功能,可以讓我指定的一些函數的參數,同時推遲全面評估:

部分(func,* args,**關鍵字) - 部分應用給定參數和關鍵字的新函數。

In [461]: from functools import partial 

In [462]: flist=[partial(func1,p=1), partial(func1,p=2)] 

In [463]: [[f(x,i) for f in flist] for i in range(3)] 
Out[463]: 
[[array([0, 0, 0]), array([0, 0, 0])], 
[array([0, 1, 4]), array([0, 1, 4])], 
[array([ 0, 4, 16]), array([ 0, 16, 64])]] 

事實上,如果我調整func1我可以分配既ip與部分:

In [464]: def func1(x,i=0,p=1): 
    return func(x*i**p) 

In [465]: flist=[partial(func1,p=1), partial(func1,p=2)]  
In [466]: fflist=[[partial(f,i=i) for f in flist] for i in range(3)] 

In [467]: fflist 
Out[467]: 
[[functools.partial(<function func1 at 0xb4d3e3d4>, i=0, p=1), 
    functools.partial(<function func1 at 0xb4d3e3d4>, i=0, p=2)], 
[functools.partial(<function func1 at 0xb4d3e3d4>, i=1, p=1), 
    functools.partial(<function func1 at 0xb4d3e3d4>, i=1, p=2)], 
[functools.partial(<function func1 at 0xb4d3e3d4>, i=2, p=1), 
    functools.partial(<function func1 at 0xb4d3e3d4>, i=2, p=2)]] 

評估這仍然需要通過嵌套列表迭代:

In [471]: [[f(x) for f in ff] for ff in fflist] 
Out[471]: 
[[array([0, 0, 0]), array([0, 0, 0])], 
[array([0, 1, 4]), array([0, 1, 4])], 
[array([ 0, 4, 16]), array([ 0, 16, 64])]] 

我可能創建了fflist,只需致電partial(對於每個「單元」):

fflist=[[partial(func1,i=i,p=p) for p in [1,2]] for i in range(3)] 

這可能是可以通過使fflist對象D型細胞陣列以簡化迭代,但是這是一個後一個問題。

還有其他包裝功能的方式供以後評估,但這些方法是最簡單和最明顯的。

我可以使用partialx參數以及

In [478]: z=[[partial(f,x) for f in ff] for ff in fflist] 

In [479]: z 
Out[479]: 
[[functools.partial(<function func1 at 0xb4d3e3d4>, array([0, 1, 2]), i=0, p=1), 
    functools.partial(<function func1 at 0xb4d3e3d4>, array([0, 1, 2]), i=0, p=2)], 
....]] 

In [480]: [[f() for f in ff] for ff in z] 
+0

我明白你實際上回答了延遲評估的問題,而不是擔心我我正在試圖解決這個問題,以及如何避免使用這種方法來完成我的任務。在SE上,經常嘗試重寫代碼,而不回答被問到的問題。 –

0

定義循環內的列表:

for i in whatever: 
    l = [func(x * i), func(x * i**2)] 

鑑於您所標記的這NumPy的,使用列表中的所有可能不是一個好主意,但我們真的不能告訴你應該是什麼從問題中回答問題。

+0

我只是想到了,但問題是,列表(3確切)是函數的所有參數。該程序嘗試初始化參數時崩潰。 –

+0

@MattF:你設計的這個功能不對,或者你試圖錯誤地使用它。你必須改變設計的某個方面才能完成這項工作。真的很難說出你在描述什麼,所以我不能說你需要改變哪一部分。 – user2357112

+0

我正在創建一個對角線矩陣,其對角線是重複模式。因此,我遍歷列表以將適當的項目放置在適當的列中。很可能有一個NumPy函數可以創建這樣的對角矩陣,這就是我爲什麼標記它的原因。 我可以發佈代碼,如果這會有所幫助,但如果有一種Pythonic方式來延遲評估,因爲Mathematica會這樣做,那將是最簡單的 –

相關問題