mirror of
https://github.com/satwikkansal/wtfpython
synced 2024-11-25 12:34:23 +01:00
Translate How not to use is operator example
This commit is contained in:
parent
e2d6ee66cc
commit
a7985b9edc
125
translations/README-ru.md
vendored
125
translations/README-ru.md
vendored
@ -331,3 +331,128 @@ False
|
|||||||
В итоге, `1 < 1` выполняется и дает результат `False`
|
В итоге, `1 < 1` выполняется и дает результат `False`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### ▶ Как не надо использовать оператор `is`
|
||||||
|
<!-- Example ID: 230fa2ac-ab36-4ad1-b675-5f5a1c1a6217 --->
|
||||||
|
Ниже приведен очень известный пример.
|
||||||
|
|
||||||
|
1\.
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> a = 256
|
||||||
|
>>> b = 256
|
||||||
|
>>> a is b
|
||||||
|
True
|
||||||
|
|
||||||
|
>>> a = 257
|
||||||
|
>>> b = 257
|
||||||
|
>>> a is b
|
||||||
|
False
|
||||||
|
```
|
||||||
|
|
||||||
|
2\.
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> a = []
|
||||||
|
>>> b = []
|
||||||
|
>>> a is b
|
||||||
|
False
|
||||||
|
|
||||||
|
>>> a = tuple()
|
||||||
|
>>> b = tuple()
|
||||||
|
>>> a is b
|
||||||
|
True
|
||||||
|
```
|
||||||
|
|
||||||
|
3\.
|
||||||
|
**Результат**
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> a, b = 257, 257
|
||||||
|
>>> a is b
|
||||||
|
True
|
||||||
|
```
|
||||||
|
|
||||||
|
**Вывод (только для Python 3.7.x)**
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> a, b = 257, 257
|
||||||
|
>>> a is b
|
||||||
|
False
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 💡 Объяснение:
|
||||||
|
|
||||||
|
**Разница между `is` и `==`**.
|
||||||
|
|
||||||
|
* Оператор `is` проверяет, ссылаются ли оба операнда на один и тот же объект (т.е. проверяет, совпадают ли идентификаторы операндов или нет).
|
||||||
|
* Оператор `==` сравнивает значения обоих операндов и проверяет, одинаковы ли они.
|
||||||
|
* Таким образом, оператор `is` предназначен для равенства ссылок, а `==` - для равенства значений. Пример, чтобы прояснить ситуацию,
|
||||||
|
```py
|
||||||
|
>>> class A: pass
|
||||||
|
>>> A() is A() # 2 пустых объекта в разных ячейках памяти
|
||||||
|
False
|
||||||
|
```
|
||||||
|
|
||||||
|
**`256` - существующий объект, а `257` - нет**.
|
||||||
|
|
||||||
|
При запуске python числа от `-5` до `256` записываются в память. Эти числа используются часто, поэтому имеет смысл просто иметь их наготове.
|
||||||
|
|
||||||
|
Перевод цитаты из [документации](https://docs.python.org/3/c-api/long.html)
|
||||||
|
> Текущая реализация хранит массив целочисленных объектов для всех целых чисел от -5 до 256, когда вы создаете int в этом диапазоне, вы просто получаете обратно ссылку на существующий объект.
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> id(256)
|
||||||
|
10922528
|
||||||
|
>>> a = 256
|
||||||
|
>>> b = 256
|
||||||
|
>>> id(a)
|
||||||
|
10922528
|
||||||
|
>>> id(b)
|
||||||
|
10922528
|
||||||
|
>>> id(257)
|
||||||
|
140084850247312
|
||||||
|
>>> x = 257
|
||||||
|
>>> y = 257
|
||||||
|
>>> id(x)
|
||||||
|
140084850247440
|
||||||
|
>>> id(y)
|
||||||
|
140084850247344
|
||||||
|
```
|
||||||
|
|
||||||
|
Интерпретатор не понимает, что до выполнения выражения `y = 257` целое число со значением `257` уже создано, и поэтому он продолжает создавать другой объект в памяти.
|
||||||
|
|
||||||
|
Подобная оптимизация применима и к другим **изменяемым** объектам, таким как пустые кортежи. Поскольку списки являются изменяемыми, поэтому `[] is []` вернет `False`, а `() is ()` вернет `True`. Это объясняет наш второй фрагмент. Перейдем к третьему,
|
||||||
|
|
||||||
|
**И `a`, и `b` ссылаются на один и тот же объект при инициализации одним и тем же значением в одной и той же строкеi**.
|
||||||
|
|
||||||
|
**Вывод**
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> a, b = 257, 257
|
||||||
|
>>> id(a)
|
||||||
|
140640774013296
|
||||||
|
>>> id(b)
|
||||||
|
140640774013296
|
||||||
|
>>> a = 257
|
||||||
|
>>> b = 257
|
||||||
|
>>> id(a)
|
||||||
|
140640774013392
|
||||||
|
>>> id(b)
|
||||||
|
140640774013488
|
||||||
|
```
|
||||||
|
|
||||||
|
* Когда a и b инициализируются со значением `257` в одной строке, интерпретатор Python создает новый объект, а затем одновременно ссылается на него во второй переменной. Если делать это в отдельных строках, интерпретатор не "знает", что объект `257` уже существует.
|
||||||
|
|
||||||
|
* Это оптимизация компилятора и относится именно к интерактивной среде. Когда вы вводите две строки в интерпретаторе, они компилируются отдельно, поэтому оптимизируются отдельно. Если выполнить этот пример в файле `.py', поведение будет отличаться, потому что файл компилируется весь сразу. Эта оптимизация не ограничивается целыми числами, она работает и для других неизменяемых типов данных, таких как строки (проверьте пример "Строки - это сложно") и плавающие числа,
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> a, b = 257.0, 257.0
|
||||||
|
>>> a is b
|
||||||
|
True
|
||||||
|
```
|
||||||
|
|
||||||
|
* Почему это не сработало в Python 3.7? Абстрактная причина в том, что такие оптимизации компилятора зависят от реализации (т.е. могут меняться в зависимости от версии, ОС и т.д.). Я все еще выясняю, какое именно изменение реализации вызвало проблему, вы можете проверить этот [issue](https://github.com/satwikkansal/wtfpython/issues/100) для получения обновлений.
|
||||||
|
|
||||||
|
---
|
||||||
|
Loading…
Reference in New Issue
Block a user