在Python中使用匿名函数

时间:2012-11-18 00:53:28

标签: python anonymous-function

我有一些代码可以从众多网址中下载数据列表,然后调用另一个函数,传入每个结果。有点像...

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

这很好但是self.Scraper.GetSubUrls运行时有很长的延迟,然后所有的UI调用都非常迅速。这会导致UI长时间显示“0 Urls added”,然后完成。

我想要的是能够将self.UI.addlink方法传递给self.Scraper.GetSubUrls方法,以便在检索到每个URL后立即调用它。一旦检索到每个URL,这应该使UI显示正确的计数。

这可能吗?如果是这样,那么正确的语法是什么?

如果我使用Javascript,我会做类似......

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

然后,在getSubUrls里面做

SomeParamMethod(Pram1, Param2)

这可能吗?如果是这样,那么正确的语法是什么?

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分:4)

这个建议比较复杂,但是如果你控制GetSubUrls,更多的Pythonic方法可能是使它成为一个生成器,在检索时生成每个URL。然后,您可以在for循环中处理函数外部的每个URL。例如,我假设GetSubUrls大概看起来像这样:

def GetSubUrls(self, url):
    urls = []
    document = openUrl(url)
    for stuff in document:
        urls.append(stuff)
    return urls

也就是说,它会构建一个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是生成器,则不等待收集所有郊区然后返回它们。它只是一次产生一个,你的代码同样可以一次处理一个。

这比传递回调的一个优点是,您可以存储生成器并随时使用它,而不是在GetSubUrls内进行调用。也就是说,您可以执行urls = GetSubUrls(url),将其保存以供日后使用,并且稍后将“按需”迭代URL,然后逐个检索它们。使用回调方法强制GetSubUrls函数立即处理所有URL。另一个优点是你不需要创建一堆内容很少的小回调;相反,你可以自然地将这些单行编写为for循环的主体。

阅读Python生成器以获取更多信息(例如What does the "yield" keyword do in Python?)。