5

我有一些代码从多个 URL 下载数据列表,然后调用另一个函数,传入每个结果。就像是...

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 后立即调用它。这应该使 UI 在检索到每个 url 后立即显示正确的计数。

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

如果我在 Javascript 中,我会做类似......

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

然后,在 getSubUrls 里面做

SomeParamMethod(Pram1, Param2)

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

4

2 回答 2

7

您可以使用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)
于 2012-11-18T00:55:53.360 回答
6

这个建议涉及更多一点,但如果您控制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 生成器以获取更多信息(例如“yield”关键字在 Python 中的作用是什么?)。

于 2012-11-18T01:04:47.510 回答