Domanda

voglio convertire il seguente codice:

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

nel codice molto più conveniente:

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

speravo di fare questo con l'affermazione with. Come ho commentato a soffietto, speravo di ottenere:

def __enter__():
    def func():

..code in the for loop..

def __exit__():
  funcs.append(func)

Naturalmente questo non funziona.

di lista non è un bene per i casi sono stati i searchForLink azione non è solo una funzione, ma molte funzioni. Si sarebbe trasformato in un codice estremamente illeggibile. Per esempio anche questo sarebbe problematico con list comprehension:

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)
È stato utile?

Soluzione

Un po 'non convenzionale, ma si può avere un decoratore registrare il func e legare tutte le variabili di loop come argomenti di default:

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

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

Altri suggerimenti

Non ha senso usare with qui. Invece di utilizzare una lista di comprensione:

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

Ci sono solo due modi per creare funzioni: def e lambda. Lambda sono pensati per le funzioni di piccole, in modo che non possano essere molto appropriato per il vostro caso. Tuttavia, se si vuole veramente, è possibile racchiudere due lambda uno dentro l'altro:

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

Un po 'troppo per i miei gusti LISPish.

Perdere la <STATEMENT>(funcs): riga

Modifica:

Voglio dire: perché si dovrebbe fare questo? Perché definire una nuova funzione per ogni pagina? Perché non farlo?

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

Non si deve usare "con" per fare questo (anche se, dato che si tratta di Python, è quasi certamente possibile, utilizzando un bizzarro effetto collaterale e dynamicism di Python).

Lo scopo di "con" in Python è, come descritto in la documentazione , "per avvolgere l'esecuzione di un blocco con metodi definiti da un contesto gestore. Ciò consente try comune ... tranne ... infine schemi di utilizzo da incapsulare per un comodo riutilizzo."

Credo che tu stai confondendo "con" con la JavaScript / VisualBasic "con", che può essere esteticamente simili, ma che è effettivamente correlati.

Il buon vecchio itertools .

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

Anche se, forse si preferisce funzionale .

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

Non credo che sia utile creare una classe per uso with: è più lavoro per creare __enter__ e __exit__ di quanto non lo è quello di scrivere solo una funzione di supporto

.

Si può essere meglio utilizzare i generatori per ottenere il calcolo ritardata che stai cercando.

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

links = MakeLinks(urls)

Quando si desidera che il link:

for link in links:
    print link

Gli URL sarà cercato nel corso di questo ciclo, e non tutti in una volta (che sembra che si sta Tring per evitare).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top