2012-07-10 21 views
2

從環境(它是一個名爲nuke的圖形程序)給出了一個全局對象,我可以添加菜單項並將它與函數連接。這個全局對象是這樣工作的:如何結合getattr()動態地使用lambda與python模塊相結合:在python中?

menu.addCommand("Do This!", lambda: DoThings()) 

我想動態讀取Python模塊和添加模塊的功能在全局菜單對象的項目。我寫了一個課程來做到這一點。我的課程的簡化版本:

class mymenu(): 
. 
. 
. 
def _builMenuFromPath(self, basepath, module): 

    items = [] 

    # ... 
    # there is code to build the items list. this is a list of the python filenames 
    # ... 

    if len(items) > 0: 

     for item in items: 

      try: 
       f = getattr(__import__(module + "." + item), item) # item is the python filename of an module in the folder with the python files and module is the folder 

       menu.addCommand(item, lambda: f.call()) # f.call() is a function in the dynamic loaded python file 

      except Exception, e: 
       pass 

動態導入工作得很好。但是每個生成的菜單項都鏈接到上次導入的函數。所以每一個菜單項都是一樣的。

我不是專業程序員。所以我認爲我犯了一個簡單的錯誤。

感謝您的幫助。

回答

0

嘗試傳遞f.call而不是lambda:f.call()。

+0

謝謝。這樣可行!!!我在那失去了半天。 – Jonas 2012-07-10 20:41:59

+0

@Jonas看看我的答案中提供的解釋。 – Marcin 2012-07-10 20:46:31

+0

@Jonas隨時。請確保將回答您的問題的答案標記爲「已回答」(旁邊的複選標記)。這會將您的問題標記爲已回答。 – Lanaru 2012-07-10 20:49:11

0

表達式lambda: f.call(),f中的問題是一個免費術語,指的是封閉範圍內的變量f。這意味着f的值的變化在lambda內部是明顯的。例如:

>>> n = 1 
>>> lambda: n 
<function <lambda> at 0x00000000027F0898> 
>>> l = lambda: n 
>>> l() 
1 
>>> n = 2 
>>> l() 
2 

然而,lambda是不必要的,因爲在python函數和方法是對象,其自身可以通過任何地方可調用(如拉姆達)可以被傳遞。在此代碼:

menu.addCommand(item, f.call) 

f.call是將評估爲是可調用一個綁定方法的表達式。

+0

謝謝。我想現在我明白lambda是如何工作的。以我的方式,它無法工作。 – Jonas 2012-07-11 17:58:18

+0

@Jonas沒問題。這是很多人需要時間來掌握的東西。繼續並投票並接受。 – Marcin 2012-07-11 19:18:02