2015-05-28 13 views
6

Diciamo che voglio creare un elenco di ints usando Python che consiste dei cubi dei numeri da 1 a 10 solo se il cubo è equamente divisibile per quattro ().Questa comprensione della lista è abbastanza pitone?

Ho scritto questa linea di lavoro:

cube4 = [x ** 3 for x in range(1, 11) if (x ** 3) % 4 == 0] 

mio manzo con questa riga di codice è che è il calcolo del cubo x due volte. C'è più pythonic modo di scrivere questa riga? O è buono come entrerà nella comprensione di una lista?


Edit - La mia domanda è destinata ad essere concentrati come evitare calcoli estranei utilizzando le funzionalità e le sfumature di Python, pur mantenendo il codice conciso e leggibile. Sebbene questa soluzione avrebbe potuto probabilmente essere raggiunta guardando altre domande, volevo essere sicuro di conoscere la migliore risposta a questa domanda, non solo una soluzione che funzioni.

+1

Così com'è, è molto pitonico e non me ne preoccuperei. Non hai idea di cosa stia facendo il runtime, potrebbe benissimo essere l'ottimizzazione del termine x^3 già. Oppure, una versione futura di Python potrebbe. O un tempo di esecuzione alternativo, come potrebbe essere PyPy. È meglio seguire gli idiomi della lingua e lasciare che i progettisti linguistici si preoccupino di questo genere di cose, a meno che tu non abbia profilato il tuo codice e * sappia * che quella comprensione delle liste è il tuo collo di bottiglia. Se arrivi a quel punto, devi preoccuparti di cosa sta facendo il tuo runtime. – LiavK

risposta

16

È possibile utilizzare un generatore di espressione:

cubed = (x ** 3 for x in range(1, 11)) 
cube4 = [c for c in cubed if c % 4 == 0] 

Questo ancora itera su range() solo volta, ma ora l'espressione x ** 3 viene calcolato solo una volta come l'espressione generatore viene iterato sopra. È possibile combinare in una sola riga:

cube4 = [c for c in (x ** 3 for x in range(1, 11)) if c % 4 == 0] 

ma mantenendo il generatore di espressione su una riga separata può essere di aiuto nella comprensione (no pun intended).

Demo:

>>> [c for c in (x ** 3 for x in range(1, 11)) if c % 4 == 0] 
[8, 64, 216, 512, 1000] 

Naturalmente, matematicamente parlando, per il semplice esempio si potrebbe utilizzare [x ** 3 for x in range(2, 11, 2)], ma ho il sospetto che non era del tutto l'obiettivo della tua domanda. :-)

+0

Mi piace molto questa soluzione di generatore. Questo è sicuramente il tipo di revisione che stavo cercando. Sarei d'accordo nel mantenere la leggibilità di primo piano in due righe anziché renderne una meno leggibile. Grazie! –

3

Il cubo di un numero è divisibile per 4 se e solo se il numero è pari. Questo è facile da vedere se espandi ogni numero nei suoi fattori primi. Pertanto:

cube4 = [x ** 3 for x in range(1, 11) if x % 2 == 0] 
+1

Certo, ma non è questo il punto della questione, sospetto. –

1

amo one-liners, ma vale la pena notare che c'è un altro modo per produrre la Pythonic list desiderato.

cube4 = [] 
for x in range(1, 11): 
    y = x ** 3 
    if not y%4: 
     cube4.append(y)