5

Ho generare un'istruzione condizionale utilizzando (2.7) eval() funzione di pitone in questo modo:C'è una lunghezza massima per un'istruzione condizionale (if) pitone?

my_list = ['2 > 1','3 > 2','4 > 3'] 

if eval('(' + ') or ('.join(my_list) + ')'): 
    print 'yes' 
else: 
    print 'no' 

Nel mio caso, l'elenco viene generato dal codice, my_list proviene da un file di parametri, e la lista si unisce con 'o 'affermazioni nell'espressione condizionale. Il codice sopra stampa 'sì'.

Funziona correttamente per elenchi di piccole dimensioni, ma con un determinato numero di caratteri nell'istruzione eval() e viene visualizzato un errore di stringa.

qualche ricerca trova questi fili che puntano a un bug:

Ma la loro eval massima dimensione è molto più grande di quello che ho trovato() . Nel mio caso, trovo tra il 1744 e il 1803 caratteri il problema inizia. Ho provato questo codice e va in crash tra le due affermazioni

>>> eval("1.0*"*10000+"1.0") 
1.0 
>>> eval("1.0*"*100000+"1.0") 
# segfault here 

Quindi, che mi riporta a pensare che non è eval(), ma in realtà un po 'max sulla dichiarazione if.

Qual è un altro modo per applicare in modo condizionale le regole nell'elenco che non include stringhe lunghe e la funzione eval()?

È interessante notare, ho fatto my_list molto più grande:

my_list = ['2 > 1']*1000000 

e il codice funziona bene ...

+0

Se l'elenco delle condizioni viene generato dal codice, perché non sono valutate immediatamente dopo generazione? Perché la conversione in stringa? –

+0

@OliverW. Le condizioni provengono da un file di configurazione. Perché sono 'o' affermazioni non vedo esattamente come valutarne uno alla volta. Credo che potrei avere un flag booleano che inizia come False e quindi è impostato su True se una delle affermazioni "if" viene valutata come True. – philshem

risposta

9

Forse mi manca qualcosa ma sembrerebbe che:

any(map(eval, my_list)) 

Fa esattamente quello che desideri.

from itertools import imap 

any(imap(eval, my_list)) # Python 2. 

Questo ha l'effetto di piacevole non valutare il resto della lista Se il primo elemento a evals True (noto anche come "corto circuito"). Questo potrebbe o non potrebbe essere quello che stai cercando.

Esempio:

> any(map(eval, ['2 > 1','3 > 2','4 > 3'])) 
True 
+2

Nota: 'map' è solo pigro in Python 3. Sotto 2.7, [' itertools.imap'] (http://docs.python.org/2/library/itertools.html#itertools.imap) può essere usato invece per ottenere lo stesso effetto. (Sto solo dicendo che OP sta usando Python 2.7.) – Carsten

+0

Questo fa esattamente quello che voglio, incluso il "cortocircuito".C'è molto odio per eval() ma non vedo un altro modo. – philshem

+1

@philshem: C'è odio per 'eval', per una buona ragione, ma esiste anche per una buona ragione. Se il tuo obiettivo è "valutare un codice Python" direi che è lo strumento più semplice per il lavoro. Prendi in considerazione le implicazioni per la sicurezza e se questo può essere un problema per te. – ereOn