Translate Strings can be tricky sometimes example to russian

This commit is contained in:
Vadim Nifadev 2024-01-30 21:33:44 +03:00
parent 86140390ad
commit c91a6073fb
1 changed files with 79 additions and 0 deletions

View File

@ -25,6 +25,8 @@ PS: Если вы уже читали **wtfpython** раньше, с измен
- [Секция: Напряги мозги!](#секция-напряги-мозги)
- [▶ Первым делом!](#-первым-делом)
- [💡 Обьяснение](#-обьяснение)
- [▶ Строки иногда ведут себя непредсказуемо](#-строки-иногда-ведут-себя-непредсказуемо)
- [💡 Объяснение](#-объяснение)
# Структура примера
@ -205,3 +207,80 @@ if a := some_func():
- Аналогично, `(a, b := 16, 19)` эквивалентно `(a, (b := 16), 19)`, которое есть не что иное, как кортеж из 3 элементов.
---
### ▶ Строки иногда ведут себя непредсказуемо
<!-- Example ID: 30f1d3fc-e267-4b30-84ef-4d9e7091ac1a --->
1\.
```py
>>> a = "some_string"
>>> id(a)
140420665652016
>>> id("some" + "_" + "string") # Обратите внимание, оба идентификатора одинаковы
140420665652016
```
2\.
```py
>>> a = "wtf"
>>> b = "wtf"
>>> a is b
True
>>> a = "wtf!"
>>> b = "wtf!"
>>> a is b
False
```
3\.
```py
>>> a, b = "wtf!", "wtf!"
>>> a is b # Актуально для версий Python, кроме 3.7.x
True
>>> a = "wtf!"; b = "wtf!"
>>> a is b # Выражение вернет True или False в зависимости вызываемой среды (python shell / ipython / скрипт).
False
```
```py
# На этот раз в файле
a = "wtf!"
b = "wtf!"
print(a is b)
# Выводит True при запуске модуля
```
4\.
**Output (< Python3.7 )**
```py
>>> 'a' * 20 is 'aaaaaaaaaaaaaaaaaaaa'
True
>>> 'a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa'
False
```
Логично, правда?
#### 💡 Объяснение
- Поведение в первом и втором фрагментах связано с оптимизацией CPython (называемой интернированием строк ((англ. string interning))), которая пытается использовать существующие неизменяемые объекты в некоторых случаях вместо того, чтобы каждый раз создавать новый объект.
- После "интернирования" многие переменные могут ссылаться на один и тот же строковый объект в памяти (тем самым экономя память).
- В приведенных выше фрагментах строки неявно интернированы. Решение о том, когда неявно интернировать строку, зависит от реализации. Правила для интернирования строк следующие:
- Все строки длиной 0 или 1 символа интернируются.
- Строки интернируются во время компиляции (`'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)).
- Единица компиляции в интерактивной среде IPython состоит из одного оператора, тогда как в случае модулей она состоит из всего модуля. `a, b = "wtf!", "wtf!"` - это одно утверждение, тогда как `a = "wtf!"; b = "wtf!"` - это два утверждения в одной строке. Это объясняет, почему тождества различны в `a = "wtf!"; b = "wtf!"`, но одинаковы при вызове в модуле.
- Резкое изменение в выводе четвертого фрагмента связано с [peephole optimization](https://en.wikipedia.org/wiki/Peephole_optimization) техникой, известной как складывание констант (англ. Constant folding). Это означает, что выражение `'a'*20` заменяется на `'aaaaaaaaaaaaaaaaaaaa'` во время компиляции, чтобы сэкономить несколько тактов во время выполнения. Складывание констант происходит только для строк длиной менее 21. (Почему? Представьте себе размер файла `.pyc`, созданного в результате выполнения выражения `'a'*10**10`). [Вот](https://github.com/python/cpython/blob/3.6/Python/peephole.c#L288) исходный текст реализации для этого.
- Примечание: В Python 3.7 складывание констант было перенесено из оптимизатора peephole в новый оптимизатор AST с некоторыми изменениями в логике, поэтому четвертый фрагмент не работает в Python 3.7. Подробнее об изменении можно прочитать [здесь](https://bugs.python.org/issue11549).
---