2013-03-06 4 views
17

Мы все знаем, синтаксиспитона список понимания с несколькими «если-х

[f(x) for x in y if g(x)] 

питона.

Однако AST представление списка понимания имеет место для более чем один «если» выражение:

comprehension = (expr target, expr iter, expr* ifs) 

Может кто-нибудь дать мне пример кода Python, который будет продуцировать AST с более чем одним «, если выражение?

ответ

28

Просто сложите их друг за другом:

[i for i in range(100) if i > 10 if i < 50] 

Производит целых чисел от 11 до 49 лет включительно.

+5

Почему это необходимо, когда 'and' бы достичь точно тот же результат? –

+3

Итак, это логично И? –

+1

Я понятия не имею, зачем это нужно, но да, это ведет себя как «и». Возможно, это не * необходимо *, а просто синтаксический сахар. –

30

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

[j for i in range(100) if i > 10 for j in range(i) if j < 20] 

осмыслению компонентов следует рассматривать как вложенные заявления, выше переводится:

lst = [] 
for i in range(100): 
    if i > 10: 
     for j in range(i): 
      if j < 20: 
       lst.append(j) 

Это также означает, что вы можете использовать несколько заявлений if без for петель между:

[i for i in range(100) if i > 10 if i < 20] 

Хотя не бы бессмысленно (просто объединить тех, кто использует and или с прикованными операторами), он переводит к юридическому вложенному набору операторов еще:

lst = [] 
for i in range(100): 
    if i > 10: 
     if i < 20: 
      lst.append(i) 

грамматика и синтаксическому анализ конкретно не DISALLOW такого использования , так же, как Python не запрещает вам вводить операторы if.

+2

Фактически, цитированная часть грамматики АСТ не обязательно обрабатывать первую часть вашего ответа. В этом примере будут созданы два генератора понимания * с одним оператором if. – poke

4

language reference дает лучшее представление об этом:

list_comprehension ::= expression list_for 
list_for   ::= "for" target_list "in" old_expression_list [list_iter] 
list_iter   ::= list_for | list_if 
list_if    ::= "if" old_expression [list_iter] 

Как вы можете видеть список понимания определяется с дополнительным list_iter в конце-одном list_iter. Теперь этот list_iter может быть либо другой частью понимания списка, либо условием if. Само условие if заканчивается еще одним необязательным list_iter. Это необходимо для обеспечения возможности объединения нескольких частей с дополнительными if-условиями в одно и то же понимание списка. Тот факт, что вы могли бы также построить часть .. if X if Y if Z для list_iter, является лишь побочным эффектом.

Таким образом, хотя возможность связывать несколько условий if не требуется, это позволяет определить всю грамматику таким образом.

-1

Попробуйте следующий код:

>>> [i for i in range(50) if i in range(10,20)] 
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 

, который дает инклюзивного результат.

2

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

>>> [x for x in range(20) if all([1 < x < 10, not x & 1])] 
[2, 4, 6, 8] 

Или

>>> [x for x in range(20) if all([foo(x), bar(x)])] 

any() встроенный также будет хорошо работать здесь, если только одно условие необходимо, чтобы быть удовлетворены:

>>> [x for x in range(20) if any([1 < x < 10, not x & 1])] 
[0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18] 
+0

Отличный ответ. Чувствуется яснее и лаконично –

+0

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

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