Translate Be careful with chained operations example

This commit is contained in:
Vadim Nifadev 2024-04-18 14:45:13 +03:00
parent c91a6073fb
commit e2d6ee66cc
1 changed files with 48 additions and 1 deletions

View File

@ -275,7 +275,7 @@ False
- После "интернирования" многие переменные могут ссылаться на один и тот же строковый объект в памяти (тем самым экономя память).
- В приведенных выше фрагментах строки неявно интернированы. Решение о том, когда неявно интернировать строку, зависит от реализации. Правила для интернирования строк следующие:
- Все строки длиной 0 или 1 символа интернируются.
- Строки интернируются во время компиляции (`'wtf'` будет интернирована, но `''.join(['w'', 't'', 'f'])` - нет)
- Строки интернируются во время компиляции (`'wtf'` будет интернирована, но `''.join(['w'', 't', 'f'])` - нет)
- Строки, не состоящие из букв ASCII, цифр или знаков подчеркивания, не интернируются. В примере выше `'wtf!'` не интернируется из-за `!`. Реализацию этого правила в CPython можно найти [здесь](https://github.com/python/cpython/blob/3.6/Objects/codeobject.c#L19)
![image](/images/string-intern/string_intern.png)
- Когда переменные `a` и `b` принимают значение `"wtf!"` в одной строке, интерпретатор Python создает новый объект, а затем одновременно ссылается на вторую переменную. Если это выполняется в отдельных строках, он не "знает", что уже существует `"wtf!"` как объект (потому что `"wtf!"` не является неявно интернированным в соответствии с фактами, упомянутыми выше). Это оптимизация во время компиляции, не применяется к версиям CPython 3.7.x (более подробное обсуждение смотрите здесь [issue](https://github.com/satwikkansal/wtfpython/issues/100)).
@ -284,3 +284,50 @@ False
- Примечание: В Python 3.7 складывание констант было перенесено из оптимизатора peephole в новый оптимизатор AST с некоторыми изменениями в логике, поэтому четвертый фрагмент не работает в Python 3.7. Подробнее об изменении можно прочитать [здесь](https://bugs.python.org/issue11549).
---
### ▶ Осторожнее с цепочкой операций
<!-- Example ID: 07974979-9c86-4720-80bd-467aa19470d9 --->
```py
>>> (False == False) in [False] # логично
False
>>> False == (False in [False]) # все еще логично
False
>>> False == False in [False] # а теперь что?
True
>>> True is False == False
False
>>> False is False is False
True
>>> 1 > 0 < 1
True
>>> (1 > 0) < 1
False
>>> 1 > (0 < 1)
False
```
#### 💡 Объяснение:
Согласно https://docs.python.org/3/reference/expressions.html#comparisons
> Формально, если a, b, c, ..., y, z - выражения, а op1, op2, ..., opN - операторы сравнения, то a op1 b op2 c ... y opN z эквивалентно a op1 b и b op2 c и ... y opN z, за исключением того, что каждое выражение оценивается не более одного раза.
Хотя такое поведение может показаться глупым в приведенных выше примерах, оно просто фантастично для таких вещей, как `a == b == c` и `0 <= x <= 100`.
* `False is False is False` эквивалентно `(False is False) и (False is False)`.
* `True is False == False` эквивалентно `(True is False) and (False == False)` и так как первая часть высказывания (`True is False`) оценивается в `False`, то все выражение приводится к `False`.
* `1 > 0 < 1` эквивалентно `(1 > 0) и (0 < 1)`, которое приводится к `True`.
* Выражение `(1 > 0) < 1` эквивалентно `True < 1` и
```py
>>> int(True)
1
>>> True + 1 # не относится к данному примеру, но просто для интереса
2
```
В итоге, `1 < 1` выполняется и дает результат `False`
---