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)