2012-11-18 117 views
4

我有一些代碼從衆多的URL下載數據列表,然後調用另一個函數,傳遞每個結果。喜歡的東西...在Python中使用匿名函數

def ShowUrls(self, url): 
    Urls = self.Scraper.GetSubUrls(url) 
    for Url in Urls: 
     self.UI.addLink(
      Url[0], 
      Url[1]) 

這工作得很好,但還有很長的延遲,而self.Scraper.GetSubUrls運行,那麼所有的用戶界面調用是由非常迅速。這會導致UI長時間顯示「0 Urls added」,然後完成。

我希望能夠將self.UI.addlink方法傳遞給方法,以便在檢索每個URL後立即調用它。這應該使得UI在每個URL被檢索後立即顯示正確的計數。

這可能嗎?如果是這樣,那麼正確的語法是什麼?

如果我是在Javascript中,我會做這樣的事情....

getSubUrls(url, function(x, y) {UI.addLink(x, y)}) 

,然後,裏面getSubUrls做

SomeParamMethod(Pram1, Param2) 

這可能嗎?如果是這樣,那麼正確的語法是什麼?

回答

6

您可以使用lambda,但通常做一個單獨的函數並傳遞它通常是一個更好的主意。

self.Scraper.GetSubUrls(url, lambda url: self.UI.addLink(url[0], url[1])) 

def addLink(url): 
    self.UI.addLink(url[0], url[1]) 

self.Scraper.GetSubUrls(url, addLink) 
+0

感謝您的快速響應。你能否稍微澄清一下 - 首選語法是什麼,爲什麼? – Basic

+0

@基本:對不起,更新了一個鏈接到文檔和更好的版本。 (請注意,您將定義嵌套在另一箇中。)它是首選,因爲它看起來更好,並且通常使代碼更簡潔。 – Ryan

+0

非常感謝,這似乎正是我所追求的。我會盡我所能接受 – Basic

4

這個建議是更多地參與一些,但如果你控制GetSubUrls,一個更Python的方法可能是讓一臺發電機能產生每個URL,因爲它是檢索。然後,您可以在for循環中處理函數外部的每個URL。舉例來說,我假設GetSubUrls大概看起來依稀像這樣:

​​

也就是說,它構建的URL列表,並返回整個列表。你可以把它發電機:

def GetSubUrls(self, url): 
    document = openUrl(url) 
    for stuff in document: 
     yield stuff 

然後,你可以做

for url in self.Scraper.GetSubUrls(url): 
    self.UI.addlink(url[0], url[1]) 

這是和以前一樣,但如果GetSubUrls是發電機,它不會等待,收集所有的suburls然後返回它們。它一次只產生一個,你的代碼可以同時處理它們。

通過回調傳遞的一個優點是您可以存儲生成器並在需要時使用它,而不必在GetSubUrls內進行調用。也就是說,您可以執行urls = GetSubUrls(url),稍後再保存該內容,並在稍後逐一檢索URL時「按需」迭代URL。使用回調方法會強制GetSubUrls函數立即處理所有URL。另一個優點是你不需要創建一堆內容很少的小回調,相反,您可以自然地將這些單線寫成for循環的主體。

請閱讀Python生成器以獲取更多相關信息(例如What does the "yield" keyword do in Python?)。

+0

是的,這是一個很好的假設:'GetSubUrls()',我喜歡這種方法 - 讓我想起其他語言的屈服。我已經實施了minitech的答案,所以已經授予他,但是+1,因爲我想我會回來,並嘗試讓我的方法儘快工作,只要我有機會。謝謝 – Basic