2009-02-12 8 views
12

Ho l'assegnazione di variabile per restituire il valore assegnato e confrontarlo con una stringa vuota, direttamente nel ciclo while.Come eseguire l'assegnazione di variabili all'interno di un ciclo while (espressione) in Python?

Ecco come lo sto facendo in PHP:

while((name = raw_input("Name: ")) != ''): 
    names.append(name) 

Quello che sto cercando di fare è identico a questo in termini di funzionalità:

names = [] 
while(True): 
    name = raw_input("Name: ") 
    if (name == ''): 
     break 
    names.append(name) 

Esiste un modo per fare questo in Python?

risposta

14
from functools import partial 

for name in iter(partial(raw_input, 'Name:'), ''): 
    do_something_with(name) 

o se si desidera un elenco:

>>> names = list(iter(partial(raw_input, 'Name: '), '')) 
Name: nosklo 
Name: Andreas 
Name: Aaron 
Name: Phil 
Name: 
>>> names 
['nosklo', 'Andreas', 'Aaron', 'Phil'] 
+0

+1 per una soluzione migliore per il wrapping di un metodo esistente. –

+0

Non una risposta; Ancora non lo so: leghi una variabile in un 'while' in Python? – Kaz

9

No, mi dispiace. È una FAQ, spiegata bene qui:

In Pydocs e Fredrik Lundh's blog.

Il motivo per cui non è consentita l'assegnazione nelle espressioni Python è un errore comune, difficile da trovare in questi altri linguaggi.

Sono state proposte molte alternative. La maggior parte sono hack che salvano un po 'di digitazione ma usano sintassi o parole chiave arbitrarie o criptiche e falliscono il semplice criterio per le proposte di cambiamento linguistico: dovrebbe suggerire intuitivamente il significato appropriato a un lettore umano che non è stato ancora introdotto nel costrutto.

Un fenomeno interessante è che i programmatori Python più esperti riconoscono l'idioma while True e non sembrano mancare molto l'assegnazione nell'espressione; sono solo i nuovi arrivati ​​che esprimono un forte desiderio di aggiungere questo alla lingua.

C'è un modo alternativo per scrivere ciò che sembra interessante:

line = f.readline() while line: 
    ... # do something with line... 
    line = f.readline() 
+0

questo link sembra essere rotto –

+0

collegamento per l'aggiornamento Aggiunto. Grazie! –

+0

Il collegamento è morto. – Makkes

12

si può avvolgere raw_input() per trasformarlo in un generatore:

def wrapper(s): 
    while True: 
     result = raw_input(s) 
     if result = '': break 
     yield result 

names = wrapper('Name:') 

che significa che siamo di nuovo al punto di partenza uno ma con codice più complesso. Quindi, se è necessario avvolgere un metodo esistente, è necessario utilizzare l'approccio nosklo.

+0

+1: battimi per secondi. Per favore aggiungi la definizione di "raw_input as generator" alla tua risposta, però. –

+0

Cool grazie! La prima volta che utilizzi lo stack overflow btw, non ho mai saputo che sarebbe stato fantastico, una risposta perfetta in pochi minuti :) –

+0

Puoi descrivere in dettaglio come "trasformare raw_input in un generatore" in modo molto pitonico? – physicsmichael

1

Sono solo 7 anni di ritardo, ma c'è un'altra soluzione. Non è la soluzione migliore a cui possa pensare, ma mette in evidenza un uso interessante dell'eccezione StopIteration. Puoi fare un ciclo simile per la lettura di file/socket e gestire Timeouts e quant'altro.

names=[] 
try: 
    while True: 
     f = raw_input() 
     if not f: 
      raise StopIteration 
     else: 
      names.append(f) 
except StopIteration: 
    pass 

print names 
1
names = [] 
for name in iter(lambda: raw_input("Name: "), ''): 
    names.append(name)