Pregunta

Quiero convertir el código siguiente:

...
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

en el código mucho más conveniente:

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

Tenía la esperanza de hacer esto con la declaración with. Como os comentaba abajo, esperaba lograr:

def __enter__():
    def func():

..code in the for loop..

def __exit__():
  funcs.append(func)

Por supuesto, esto no funciona.

Las listas por comprensión no es bueno para los casos fueron los searchForLink la acción no es sólo una función, pero muchas funciones. Se convertiría en un código muy ilegible. Por ejemplo, incluso esto podría ser problemático con las listas por comprensión:

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)
¿Fue útil?

Solución

Un poco convencional, pero puede tener un decorador de registrar el func y enlazar cualquier variable de bucle como argumentos por defecto:

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

for url in urls:
    @funcs.append
    def func(url=url):
        page = open(url)
        link = searchForLink(page)
        links.append(link)

Otros consejos

No tiene sentido utilizar with aquí. En lugar de utilizar una lista de comprensión:

funcs = [getFunc(url, links) for url in urls]

Sólo hay dos maneras de crear funciones: def y lambda. Lambdas son para pequeñas funciones, por lo que pueden no ser muy apropiado para su caso. Sin embargo, si realmente desea, puede incluir dos lambdas uno dentro de otro:

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

Un poco demasiado LISPish para mi gusto.

Pierde la <STATEMENT>(funcs): línea

Editar:

Es decir: ¿por qué haces esto? ¿Por qué definir una nueva función para cada página? ¿Por qué no acaba de hacer esto?

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

No use "con" para hacer esto (a pesar de que, dado que es Python, es casi seguro que podría, utilizando algún extraño efecto secundario y dynamicism de Python).

El propósito de "con" en Python es, como se describe en los documentos , "para envolver la ejecución de un bloque con los métodos definidos por un gestor de contexto. Esto permite que intento común ... excepto ... finalmente patrones de uso para ser encapsulado para su reutilización conveniente."

Creo que estás confundiendo "con" con el Javascript / VisualBasic "con", que puede ser cosméticamente similar pero que es efectivamente no relacionado.

itertools .

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

A pesar de que, tal vez usted prefiere funcional.

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

No creo que vale la pena crear una clase para uso with: es más trabajo para crear __enter__ y __exit__ de lo que es simplemente escribir una función de ayuda

.

Usted puede ser mejor usar generadores de lograr el cómputo retraso que está buscando.

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

links = MakeLinks(urls)

Cuando se desea que el enlaces:

for link in links:
    print link

Las direcciones URL se pueden consultar en este bucle, y no todos a la vez (que parece que estés Tring para evitar).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top