4

我想转换以下代码:

...
urls = [many urls]
links = []
funcs = []
for url in urls:
   func = getFunc(url, links)
   funcs.append(func)
...

def getFunc(url, links):
   def func():
      page = open(url)
      link = searchForLink(page)
      links.append(link)
   return func

进入更方便的代码:

urls = [many urls]
links = []
funcs = []
for url in urls:
   <STATEMENT>(funcs):
        page = open(url)
        link = searchForLink(page)
        links.append(link)

我希望通过声明来做到这一点with。正如我在下面评论的那样,我希望实现:

def __enter__():
    def func():

..code in the for loop..

def __exit__():
  funcs.append(func)

当然,这是行不通的。

列表推导不适用于动作searchForLink不仅仅是一个功能而是多个功能的情况。它会变成一个非常不可读的代码。例如,即使这对于列表推导也会有问题:

for url in urls:
  page = open(url)
  link1 = searchForLink(page)
  link2 = searchForLink(page)
  actionOnLink(link1)
  actionOnLink(link2)
  .... many more of these actions...
  links.append(link1)
4

7 回答 7

6

在这里使用没有意义with。而是使用列表推导:

funcs = [getFunc(url, links) for url in urls]
于 2010-02-04T13:55:27.810 回答
4

有点不合常规,但您可以让装饰器注册 func 并将任何循环变量绑定为默认参数:

urls = [many urls]
links = []
funcs = []

for url in urls:
    @funcs.append
    def func(url=url):
        page = open(url)
        link = searchForLink(page)
        links.append(link)
于 2010-02-04T18:12:09.690 回答
2

丢线<STATEMENT>(funcs):

编辑:

我的意思是:你为什么要这样做?为什么要为每个页面定义一个新函数?为什么不这样做呢?

urls = [many urls]
links = []
for url in urls:
    page = open(url)
    link = searchForLink(page)
    links.append(link) 
于 2010-02-04T13:45:58.393 回答
2

创建函数只有两种方法:deflambda. Lambda 用于小型函数,因此它们可能不太适合您的情况。但是,如果你真的想要,你可以将两个 lambda 封装在一起:

urls = [many urls]
links = []
funcs = [(lambda x:
            lambda:
              links.append(searchForLink(open(x))))(u)
         for u in urls]

对我的口味来说有点过于口齿不清了。

于 2010-02-04T13:56:25.923 回答
1

你不应该使用“with”来做到这一点(尽管,鉴于它是 Python,你几乎可以肯定可以使用一些奇怪的副作用和 Python 的动态性)。

如文档中所述,Python 中“with”的目的是“用上下文管理器定义的方法包装块的执行。这允许封装常见的 try...except...finally 使用模式方便重复使用。”

我认为您将 Python 的“与”与Javascript / VisualBasic的“与”混淆了,这可能在外观上相似,但实际上并不相关。

于 2010-02-04T15:01:11.737 回答
1

好旧的迭代工具

from itertools import imap
links.extend(imap(searchForLink, imap(open, urls)))

虽然,也许您更喜欢功能性.

from functional import *
funcs = [partial(compose(compose(links.append, searchForLink), open), url) for url in urls]
for func in funcs: func()

我不认为创建一个类来with使用是值得的:创建一个比编写一个辅助函数更费力的工作__enter____exit__

于 2010-02-04T15:11:22.993 回答
1

您可能会更好地使用生成器来实现您所追求的延迟计算。

def MakeLinks(urls):
    for url in urls:
        page = open(url)
        link = searchForLink(page)
        yield link

links = MakeLinks(urls)

当你想要链接时:

for link in links:
    print link

将在此循环期间查找 url,而不是一次全部查找(看起来您正在努力避免)。

于 2010-02-05T00:34:09.003 回答