在Python中使用匿名函数

Bas*_*sic 4 python anonymous-function

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

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

这很好但运行时有很长的延迟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)})
Run Code Online (Sandbox Code Playgroud)

然后,在getSubUrls里面做

SomeParamMethod(Pram1, Param2)
Run Code Online (Sandbox Code Playgroud)

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

Ry-*_*Ry- 6

您可以使用lambda,但通常更好的做法是创建一个单独的函数并传递它.

self.Scraper.GetSubUrls(url, lambda url: self.UI.addLink(url[0], url[1]))
Run Code Online (Sandbox Code Playgroud)

要么

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

self.Scraper.GetSubUrls(url, addLink)
Run Code Online (Sandbox Code Playgroud)


Bre*_*arn 5

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

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

也就是说,它构建一个 URL 列表并返回整个列表。您可以将其设为生成器:

def GetSubUrls(self, url):
    document = openUrl(url)
    for stuff in document:
        yield stuff
Run Code Online (Sandbox Code Playgroud)

然后你可以做

for url in self.Scraper.GetSubUrls(url):
    self.UI.addlink(url[0], url[1])
Run Code Online (Sandbox Code Playgroud)

和之前一样,但是如果GetSubUrls是生成器,它不会等待收集所有的子网址然后返回它们。它一次只产生一个,您的代码同样可以一次处理一个。

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

阅读 Python 生成器以获取更多信息(例如Python 中的“yield”关键字有什么作用?)。