В этом вопросе встречается код, который в упрощенном виде можно записать так:
>>> '1' in '111' == True
False
Почему так происходит? Ведь согласно таблице "Operator precedence" и in и == имеют одинаковый приоритет и должно выполняться слева направо.
Т.е. логично предположить что данная конструкция равнозначна:
>>> ('1' in '111') == True
True
Ответы
Ответ 1
Воспользуемся модулем dis, для анализа байткода
import dis
dis.dis("'1' in '111' == True")
Получим следующий вывод
1 0 LOAD_CONST 0 ('1')
2 LOAD_CONST 1 ('111')
4 DUP_TOP
6 ROT_THREE
8 COMPARE_OP 6 (in)
10 JUMP_IF_FALSE_OR_POP 18
12 LOAD_CONST 2 (True)
14 COMPARE_OP 2 (==)
16 RETURN_VALUE
>> 18 ROT_TWO
20 POP_TOP
22 RETURN_VALUE
Инструкция LOAD_CONST загружает константы в стек, DUP_TOP дублирует значение вершин
стека и добавляет его в стек, ROT_THREE поднимает 2 и 3 значения в стеке на 1 позици
вверх, опуская значение вершины стека на позицию 3. Таким образом перед операцией in (смещение 8) в стеке хранятся значения ['111', '1', '111']. Далее возможны два варианта развития событий:
В случае получения ложного значения переходим на смещение 18 со стеком [False, '111']
ROT_TWO обменяет верхние два значения стека получим стек ['111', False]. POP_TOP удалит '111' и RETURN_VALUE вернет False.
В случае получения истинного значения после выполнения LOAD_CONST на смещении 12
в стеке будет содержатся следующие значения [True, '111']. Далее происходит операция сравнения значений True и '111', результат которой помещается в стек и затем возвращается.
Получается что результат выполнения выражения '1' in '111' == True будет равен результату выполнения '1' in '111' and '111' == True
Ответ 2
Похоже данная конструкция воспринимается как "chained comparison" наподобие:
a < b <= c
что эквивалентно
a < b and b <= c
т.е.
'1' in '111' == True
будет обрабатываться как:
'1' in '111' and '111' == True
проверим догадку:
>>> '1' in '111' == '111'
True
Комментариев нет:
Отправить комментарий