2009-04-27 11 views
13

Czy można uzyskać dostęp do poprzedniego elementu wygenerowanego w zrozumieniu listy.Zrozumienie listy w języku Python - dostęp do ostatnio utworzonego elementu?

Pracuję nad elementami szyfrowania zabawek. Biorąc pod uwagę klucz jako dowolnie dużą liczbę całkowitą, wartość inicjalizacyjną i listę elementów jako wiadomość do szyfrowania. Potrzebuję xor każdego elementu z poprzednim zaszyfrowanym elementem i kluczem. Wykonałoby następującą pętlę.

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

czuję się jak powinno być możliwe, aby przekształcić to listowego, ale nie jestem do końca pewien, jak obsługiwać zarówno wartość początkową lub dostępu poprzednią wartość wygenerowaną. Czy to możliwe, a jeśli tak, jakie byłoby zrozumienie?

Odpowiedz

14

Nie ma dobrego, Pythonicznego sposobu, aby to zrobić ze zrozumieniem listy. Najlepszym sposobem myślenia o sprawdzaniu listy jest zastępowanie map i filter. Innymi słowy, można użyć wyrażeń listowych, kiedy trzeba wziąć listę i

  • Użyj jej elementy jak wejście do jakiegoś wyrażenia (np kwadratury elementy)

  • usunąć niektóre z jego elementów na podstawie pewnego warunku:

To wszystko łączy w sobie to, że każdy z nich patrzy na pojedynczy element listy naraz. To dobra zasada; nawet jeśli teoretycznie mógłbyś napisać kod, który pokazałeś jako zrozumienie listy, byłby niezręczny i niepytonowy.

+5

+1: To dlaczego wciąż mamy instrukcji for - w sytuacjach, dokładnie tak, jak to pytanie. –

1

Można użyć obiektu pomocnika do przechowywania cały stan wewnętrzny podczas iteracji nad sekwencji:

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] 

Mając na uwadze powyższe, dodając wcześniej zaszyfrowany element do xor nie robi algorytmu każdy trudniej przerwać niż tylko xoring każdego elementu za pomocą klucza. Atakujący może po prostu xor dowolny znak w tekście szyfru z poprzednią zaszyfrowaną postacią, a więc anulować xor, który został zrobiony podczas szyfrowania.

3

Mogłeś to zrobić, używając reduce(). To nie listy ze zrozumieniem, ale to podejście styl funkcjonalny:

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

To nie lada ładniejsza niż zwykły pętli w tym przypadku chociaż.

+1

Sprawdź wydajność przed użyciem zmniejsz; często może prowadzić do wyjątkowo nieefektywnych struktur. –

+1

Wersja "pętli for" jest * znacznie * czystsza, więc traktuj tę odpowiedź tylko jako "teoretycznie możliwą do wykonania w inny sposób". –

3

jako generator:

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

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

Podoba mi się to rozwiązanie, mimo że to nie jest to, co OP zadawał. – MaLiN2223

Powiązane problemy