2009-04-27 14 views
13

Ist es möglich, auf das vorherige Element zuzugreifen, das in einem Listenverständnis generiert wurde?Python Liste Verständnis - Zugang zuletzt erstellt Element?

Ich arbeite an einigen Spielzeugverschlüsselung Zeug. Gegeben sei der Schlüssel als beliebig große ganze Zahl, ein Initialisierungswert und eine Liste von Elementen als zu verschlüsselnde Nachricht. Ich muss jedes Element mit dem vorherigen chiffrierten Element und dem Schlüssel xorieren. Die folgende Schleife würde tun.

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

Ich fühle mich wie es möglich sein soll, diese in eine Liste Verständnis zu drehen, aber ich bin nicht ganz sicher, wie sowohl den Anfangswert zu behandeln oder den vorherigen Wert erzeugt zugreifen. Ist es möglich und wenn ja, wie wäre das Verständnis?

Antwort

14

Es gibt keinen guten, pythonischen Weg, dies mit einem Listenverständnis zu tun. Der beste Weg, Listenüberlegungen zu denken, ist als Ersatz für map und filter. Mit anderen Worten, würden Sie eine Liste Verständnis verwenden, wenn Sie eine Liste und

  • Verwenden Sie seine Elemente als Eingabe für einige Ausdruck nehmen müssen (zB die Elemente quadriert)

  • einige seiner Elemente entfernen basierend auf einer Bedingung

Was diese Dinge gemeinsam haben ist, dass sie jeweils nur ein einzelnes Listenelement gleichzeitig betrachten. Das ist eine gute Faustregel. Selbst wenn Sie theoretisch den Code schreiben könnten, den Sie als Listenverständnis gezeigt haben, wäre es peinlich und unpythonisch.

+5

+1: Deshalb haben wir die noch Aussage haben - für Situationen, genau wie diese Frage. –

1

Sie könnten ein Hilfsobjekt verwenden, um alle internen Zustand zu speichern, während über die Sequenz iterieren:

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] 

aber sagen, dass das Hinzufügen der zuvor verschlüsselten Element in das xor nicht Ihren Algorithmus machen noch schwerer zu brechen als nur jedes Element mit dem Schlüssel zu xorieren. Ein Angreifer kann einfach ein beliebiges Zeichen im Chiffretext mit dem vorherigen verschlüsselten Zeichen xorieren und so die xor, die während der Verschlüsselung ausgeführt wurde, löschen.

3

Sie hätten dies mit reduce() tun können. Es ist nicht das Verständnis Liste, aber es ist der funktionale Stil Ansatz:

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

Es ist nicht hübscher als die Ebene Schleife in diesem Fall aber.

+1

Überprüfen Sie die Leistung vor der Verwendung reduzieren; es kann oft zu bemerkenswert ineffizienten Strukturen führen. –

+1

Die 'for-loop'-Version ist * viel * sauberer, also behandeln Sie diese Antwort nur als "theoretisch möglich anders". –

3

als Generator:

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

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

Ich mag diese Lösung, obwohl es nicht das ist, was OP gefragt hat. – MaLiN2223

Verwandte Themen