Непоследовательный синтаксис понимания?

Я просто наткнулся на то, что, по-видимому, является недостатком синтаксиса 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]