2009-04-27 4 views
13

Возможно ли получить доступ к предыдущему элементу, сгенерированному в понимании списка.Python list comprehension - доступ к последнему созданному элементу?

Я работаю над некоторыми материалами для шифрования игрушек. Учитывая ключ как произвольное большое целое число, значение инициализации и список элементов в качестве сообщения для шифрования. Мне нужно, чтобы каждый элемент с предыдущим зашифрованным элементом и ключом. Будет выполнен следующий цикл.

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

Я чувствую, что это должно быть возможным, чтобы превратить это в список понимания, но я точно не знаю, как обрабатывать как начальное значение или доступа к предыдущему значению генерируется. Возможно ли, и если да, то каким было бы понимание?

ответ

14

Существует не хороший, Pythonic способ сделать это со списком. Лучший способ подумать о списках заключается в замене map и filter. Другими словами, вы бы использовать список понимание, когда вам нужно взять список и

  • Используйте его элементы в качестве входных данных для некоторого выражения (например, возведение в квадрат элементов)

  • удалить некоторые из его элементов на основе некоторых условий

Что общего у этих вещей состоит в том, что каждый из них смотрит только на один элемент списка за раз. Это хорошее эмпирическое правило; даже если бы вы могли теоретически написать код, который вы показали как понимание списка, это было бы неудобно и бесстрашно.

+5

+1: Вот почему у нас еще есть для заявления - для ситуаций точно, как этот вопрос. –

1

Вы можете использовать вспомогательный объект для хранения всего внутреннего состояния во время прохода по последовательности:

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] 

При этом, добавляя ранее зашифрованный элемент в исключающем не делает ваш алгоритм любой сложнее перерыв, чем просто xor'ing каждого элемента с ключом. Злоумышленник может просто использовать любой символ в шифрованном тексте с предыдущим зашифрованным символом и, таким образом, отменить xor, который был выполнен во время шифрования.

3

Вы могли бы сделать это, используя reduce(). Это не список понимания, но это функциональный подход стиля:

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

Это не какая-нибудь красивее, чем простой цикл в этом случае, хотя.

+1

Проверьте эффективность перед использованием уменьшения; это может часто приводить к чрезвычайно неэффективным структурам. –

+1

Версия для петли * очень * очиститель, поэтому трактуйте этот ответ только как «теоретически можно сделать иначе». –

3

Как генератор:

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

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

Мне нравится это решение, хотя это не то, что задал ОП. – MaLiN2223