Непоследовательный синтаксис понимания?
Я просто наткнулся на то, что, по-видимому, является недостатком синтаксиса python - иначе я что-то пропустил.
Смотрите это:
[x for x in range(30) if x % 2 == 0]
Но это синтаксическая ошибка:
[x for x in range(30) if x % 2 == 0 else 5]
Если у вас есть предложение else
, вы должны написать:
[x if x % 2 == 0 else 5 for x in range (30)]
Но это синтаксическая ошибка:
[x if x %2 == 0 for x in range(30)]
Что мне не хватает? Почему это так непоследовательно?
Ответы
Ответ 1
Здесь вы смешиваете синтаксис. В игре есть два различных концепций:
-
Синтаксис синтаксиса списка. Здесь if
действует как фильтр; включить значение в итерацию или нет. Нет else
, так как это уже "не включать".
-
A условное выражение. Это всегда должно возвращать значение, либо результат выражения "true", либо "false".
Ответ 2
Что мне не хватает?
Ниже приведена тройная операция (иначе говоря, условное выражение "на языке python)
x if some_boolean else y
Это оценивает, как будто он читает: if some_boolean
is True
, дайте мне x
, иначе дайте мне y.
Не путайте это с синтаксисом понимания:
(expression) for (iteration variable) in (iterable) [if (filter)]
Условное выражение может войти в часть (выражение). Он не имеет ничего общего с опциональной частью if (filter)
.
Ответ 3
Разница между ними заключается в том, что конечный if
в первом состоит из синтаксиса понимания списка, а if-else
является условным оператором, а не какой-либо частью синтаксиса понимания списка - поскольку это выражение, которое разрешено в этой части понимания списка.
Синтаксис для условного оператора выглядит следующим образом:
x if condition1 else y
Это возвращает значение выражения, которое оценивается, поэтому оно кажется "работающим" для вашего случая, хотя оно все время проверяет и возвращает всегда, что является ключевым отличием между ними.
В то же время, для понимания списка, он проверяет, применяется ли это условие, а не добавляет его в новый список, созданный, если условие не оценивается как true в соответствии с Процедура проверки достоверности истины, а не None
и ничего другого.
Сравните следующее (пример с PEP202):
a = [i if i % 2 == 0 else None for i in range(20)]
b = [i for i in range(20) if i % 2 == 0]
a
будет
[0, None, 2, None, 4, None, 6, None, 8, None, 10, None, 12, None, 14, None, 16, None, 18, None]
тогда как b
будет
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
который не является тем же самым, как бы ни был его результатом, он все равно добавит его, если нет части if
для понимания списка.
Ответ 4
Первый if
предназначен для условного выражения. Второй if
- для фильтра.
И, фактически, вы можете использовать их оба - этот пример должен хорошо очистить вещи:
>>> [x if x % 2 == 0 else x + 100000 for x in range(30) if x in range(13, 21)]
[100013, 14, 100015, 16, 100017, 18, 100019, 20]