2009-04-27 17 views
13

E 'possibile accedere all'elemento precedente generato in una comprensione di lista.Comprensione degli elenchi Python - accedi all'ultimo elemento creato?

Sto lavorando su alcune cose di crittografia giocattolo. Data la chiave come un numero arbitrariamente grande, un valore di inizializzazione e un elenco di elementi come il messaggio da crittografare. Ho bisogno di xorare ogni elemento con l'elemento cifrato precedente e la chiave. Il ciclo seguente farebbe.

previous = initialization_value 
cipher = [] 
for element in message: 
    previous = element^previous^key 
    cipher.append(previous) 

mi sento come dovrebbe essere possibile trasformare questo in una lista di comprensione, ma io non sono esattamente sicuro di come gestire sia il valore iniziale o accedere al valore precedente generato. E 'possibile e se sì, quale sarebbe la comprensione?

risposta

14

Non c'è un buon modo, Python, per farlo con una lista di comprensione. Il modo migliore per pensare alle list comprehensions è come sostituire map e filter. In altre parole, devi usare una lista di comprensione ogni volta che è necessario prendere una lista e

  • utilizzare i suoi elementi come input per un po 'di espressione (ad esempio, gli elementi di quadratura)

  • rimuovere alcuni dei suoi elementi in base ad alcune condizioni

Ciò che queste cose hanno in comune è che ognuna guarda un solo elemento di lista alla volta. Questa è una buona regola empirica; anche se potessi teoricamente scrivere il codice che hai mostrato come una lista di comprensione, sarebbe scomodo e non piterico.

+5

+1: Ecco perché abbiamo ancora l'istruzione for - per le situazioni esattamente come a questa domanda. –

1

È possibile utilizzare un oggetto helper per memorizzare tutti lo stato interno, mentre l'iterazione di sequenza:

class Encryption: 
    def __init__(self, key, init_value): 
    self.key = key 
    self.previous = init_value 
    def next(self, element): 
    self.previous = element^self.previous^self.key 
    return self.previous 

enc = Encryption(...) 
cipher = [enc.next(e) for e in message] 

Detto questo, aggiungendo l'elemento precedentemente cifrato nella xor non rende l'algoritmo più difficile da rompere che solo xorare ogni elemento con la chiave. Un utente malintenzionato può solo o qualsiasi carattere nel testo cifrato con il carattere crittografato precedente e quindi annullare l'xor che è stato fatto durante la crittografia.

3

Avresti potuto farlo utilizzando reduce(). Non è di lista, ma è l'approccio stile funzionale:

cipher = [] 
def f(previous, element): 
    previous = element^previous^key 
    cipher.append(previous) 
    return previous 
reduce(f, message, initialization_value) 

Non è alcuna più bella di loop pianura in questo caso però.

+1

Controllare le prestazioni prima di utilizzare ridurre; spesso può portare a strutture notevolmente inefficienti. –

+1

La versione 'for loop' è * molto * più pulita, quindi considera questa risposta solo come "teoricamente possibile fare altrimenti". –

3

come generatore:

def cypher(message, key, seed): 
    for element in message: 
     seed = element^seed^key 
     yield seed 

list(cypher(message, key, initial_seed)) 
+0

Mi piace questa soluzione anche se non è quello che ha chiesto OP. – MaLiN2223

Problemi correlati