Python, что означает 'и / или' в выражении, и что `(не i%2)` тестирует?

Я изучаю понимание списка Python и видел использование, и я не мог найти объяснения в официальном документе.

>>>[(not i%2)*'a' or str(i) for i in range(10)]
>>>['a', '1', 'a', '3', 'a', '5', 'a', '7', 'a', '9']

Я пытаюсь абстрагировать это использование таким образом:

[statement1 or statement2 for i in range(10)]

и если Statement1 оценивается как ложный, то используйте оператор 2, я прав?

Я также обнаружил, что, если я запускаю следующую команду:

>>> [(not i%2)*'a' and str(i) for i in range(10)]

Выход будет:

>>> ['0', '', '2', '', '4', '', '6', '', '8', '']

Как я должен понимать это?

4 ответа

Решение

Вот так. Странная часть - это первое выражение:

(не я%2)*'а'

Если я нечетный, то это означает "а"; если даже, это Ложь. Это вопиющее злоупотребление (известный трюк эксперта) логическим определением в Python.

Если вы представляете True как 1 и False как 0, это имеет смысл. Если продукт равен 0, оператор или принимает его как False.

Это также использует преимущество короткого замыкания выражения: если левый элемент или равен True, то правый элемент вообще не оценивается, и этот левый элемент становится значением выражения.

Точно так же в вашем последующем примере, и замыкание работает по-другому: если левый элемент имеет значение False, то он становится результатом; в противном случае правильный элемент становится результатом.

Если вы превратите это в список кортежей (с обоими условиями), вам будет легче увидеть, что происходит:

>>> [((not i%2)*'a', str(i)) for i in range(10)]
[('a', '0'), ('', '1'), ('a', '2'), ('', '3'), ('a', '4'), ('', '5'), ('a', '6'), ('', '7'), ('a', '8'), ('', '9')]

Любое нечетное значение I производит '' который False в смысле Python. or затем оценивает правую часть и возвращает ее, а не левую:

>>> 'LH' or 'RH'
'LH'
>>> '' or 'RH'
'RH'

Это лучше сформулировать как условное выражение, потому что его легче читать:

>>> ['a' if i%2==0 else str(i) for i in range(10)]
['a', '1', 'a', '3', 'a', '5', 'a', '7', 'a', '9']

Здесь или вернуть первое значение, которое можно оценить как True, Поэтому, если первое возвращаемое значение оператора может быть оценено как True, просто используйте его или найдите следующее значение. Попробуйте добавить больше "или"

 [(not i%3)*'a' or (not i%5)*'b'  or 'c' for i in range(10)]
 => ['a', 'c', 'c', 'a', 'c', 'b', 'a', 'c', 'c', 'a']

И возвращает последнее значение, только если все значения могут быть оценены как True

В заявлении поясняется:

not i%2: i % 2 оценивает 0 для четных целых чисел, 1 для нечетных целых чисел. not приведет к логическому значению, которое отрицает следующее выражение. not 1 => False, а также not 0 => True,

(True)*'a' => 1 * 'a' => 'a'

(False)*'a' => 0 * 'a' => ''

'', при приведении к логическому, оценивается как False

False or str(i) => str(i)

Другие вопросы по тегам