2013-09-18 3 views
1

В попытке использовать список понимание, чтобы сделать список дан условный, я вижу следующее:оценка списковых в питона

In [1]: mydicts = [{'foo':'val1'},{'foo':''}] 

In [2]: mylist = [d for d in mydicts if d['foo']] 

In [3]: mylist 
Out[3]: [{'foo': 'val1'}] 

In [4]: mydicts[1]['foo'] = 'val2' 

In [5]: mydicts 
Out[5]: [{'foo': 'val1'}, {'foo': 'val2'}] 

In [6]: mylist 
Out[6]: [{'foo': 'val1'}] 

Я читал документацию, чтобы попытаться понять это, но есть ничего не придумайте, поэтому я задам свой вопрос здесь: почему так, что mylist никогда не включает {'foo': 'val2'}, хотя ссылка в списке постигает mydict, что In [6] содержит {'foo': 'val2'}? Это потому, что Python охотно оценивает понимание списков? Или это ленивая/нетерпеливая дихотомия, совершенно не относящаяся к этому?

ответ

3

Я думаю, вы немного смущены тем, что понимают списки.

Когда вы сделаете это:

[d for d in mydicts if d['foo']] 

Это вычисляется в новый список. Итак, когда вы делаете это:

mylist = [d for d in mydicts if d['foo']] 

Вы назначая этот список в качестве значения mylist. Вы можете увидеть это очень легко:

assert type(mylist) == list 

Вы не назначая «список понимание», который получает перепроверены каждый раз mylist. В Python нет волшебных значений, которые каждый раз пересматриваются. (Вы можете поддельные них, например, создавая class с @property, но это на самом деле не является исключением, это выражение myobj.myprop, который будучи перепроверены, не myprop сам.)


В самом деле, mylist = [d for d in mydicts if d['foo']] является в основном то же самое mylist = [1, 2, 3]. * В обоих случаях вы создаете новый список и назначаете его mylist. Вы не ожидали, что второй повторит оценку [1, 2, 3] каждый раз (в противном случае выполнение mylist[0] = 0 не принесет пользы, потому что, как только вы попытаетесь просмотреть mylist, вы получите новый, нетронутый список!). То же самое верно и здесь.

* В Python 3.x они не только в основном такие же; они представляют собой просто разные типы отображения списка. В 2.x это немного более мрачно, и им просто приходится оценивать новые объекты списка.

0

mylist содержит результат оценки понимания предыдущего списка, он не будет обновляться магией только потому, что вы обновляете переменную, которая использовалась для его вычисления.

3

Нет никакой ленивой оценки списков в Python. Перечисление списков просто создает новый список. Если вы хотите «ленивую» оценку, используйте вместо нее generator expression.

my_generator_expression = (d for d in mydicts if d['foo']) # note parentheses 
mydicts[1]['foo'] = 'val2' 
print(my_generator_expression) # >>> <generator object <genexpr> at 0x00000000> 
for d in my_generator_expression: 
    print(d) # >>> {'foo': 'val1'} 
      # >>> {'foo': 'val2'} 

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

+1

Я не думаю, что это то, что ему нужно.Он уже распечатывает все ценности; изменение списка источников и распечатка всех свойств снова просто не даст ему ничего, потому что он уже исчерпал итератор. – abarnert

+0

@abarnert Я сделал вывод своей консоли просто удобным способом попробовать несколько разных вещей в формате, пригодном для примера, но я также сделаю заметку о возможности повторного использования генераторов. –

Смежные вопросы