2013-07-24 2 views
1

Существует список объектов, «игр». Как я могу проверить, установлен ли у объекта атрибут, а если нет, укажите атрибут .... используя списки?Изменить Loop на Python List Comprehension

for g in games: 
     if not g.score_ratio_h1: g.score_ratio_h1 = avg_score_ratio_h1 
+3

На мой взгляд, это не очень хороший пример использования для списка. Перечисления списков лучше всего подходят, когда вы выполняете фильтрацию и проекцию функционального стиля, не изменяя исходные элементы. Здесь вы мутируете каждую игру. – recursive

+1

Если вы не видите 'append()' в своем цикле где-то, это, вероятно, не представляется возможным в качестве понимания списка. – kindall

+1

Следующая ссылка о том, почему следует избегать понимания списка с побочным эффектом http://stackoverflow.com/questions/5753597/is-it-pythonic-to-use-list-comprehensions-for-just-side-effects –

ответ

4

Это не хороший случай для использования списковых, на самом деле: it's very anti-Pythonic. Цикл не приводит к созданию нового списка значений, это всего лишь последовательность назначений. Лучше придерживаться использования цикла, это нормально, как есть. Только если ваш код выглядит так:

ans = [] 
for g in games: 
    if not g.score_ratio_h1: 
     ans.append(g.score_ratio_h1) # we're appending the results 

... Тогда было бы неплохо использовать понимание. Но в настоящее время ядро ​​цикла является назначение:

g.score_ratio_h1 = avg_score_ratio_h1 

И никакого полезным возвращает значение этого, это операция модификации (а «побочный эффект»), который не получает собран в любом месте. Понятия не предназначены для использования в таких случаях. Даже больше: пытаясь сделать задание внутри понимания приведет к ошибке, например:

lst = [[0], [0], [0]] 
[a[0] = 1 for a in lst] 
    ^
SyntaxError: invalid syntax 
0

хорошо вы можете сделать что-то вроде этого, который использует список понимание:

for g in (g for g in games if not g.score_ratio_h1): 
    g.score_ratio_h1 = avg_score_ratio_h1 

это может быть возможно, немного быстрее ... но странно :)

EDIT:

Я согласен с этими двумя комментариями, однако он не может быть полностью расточителен в зависимости от «если» состояния, ее е пример:

lst = [0 for _ in xrange(708)] 
    for i in xrange(100000000): 
     if i**2 < 500000: 
      lst[i] += i 

время:

real 0m12.906s 
user 0m12.876s 
sys  0m0.008s 

против:

lst = [0 for _ in xrange(708)] 
for i in (i for i in xrange(100000000) if i**2 < 500000): 
    lst[i] += i 

время:

real 0m8.857s 
user 0m8.792s 
sys 0m0.016s 

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

+3

Это будет создайте новый список, который будет отброшен сразу же после окончания итерации. Это расточительно, я не думаю, что это хорошая идея, использующая понимание только для этого, когда достаточно «традиционной» петли. –

+1

Loop всегда дорогостоящий, и в вышеупомянутом решении есть два цикла, но в коде есть один цикл. –

+1

Если бы вы поставили здесь выражение генератора вместо понимания списка, было бы хорошо: 'for g in (g для g в играх, если не g.score_ratio_h1):' Просто замените '[]' на '()' , – glglgl