我有一些代码可以从众多网址中下载数据列表,然后调用另一个函数,传入每个结果。有点像...
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)
这可能吗?如果是这样,那么正确的语法是什么?
答案 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?)。