Почему в Python возвращается существующий объект вместо создания нового объекта?

Как можно гарантировать создание нового объекта при каждом вызове `set()` в Python, и какова логика создания встроенных объектов в Python? Как можно обеспечить уникальные объекты при использовании `set()` и других встроенных типов данных, и где можно найти подробные сведения об этом в документации? Например, код ниже создает только один объект set, а не три, как ожидалось. Dealing with Python built-in types creation logic. 
  • 2 января 2024 г. 17:27
Ответы на вопрос 3
Python использует особую логику для работы с встроенными объектами. Она основана на принципе кэширования (caching) и позволяет повторно использовать уже существующие объекты, вместо создания новых, чтобы повысить эффективность программы и экономить память.

В случае с типом данных `set()`, Python использует кэширование и множества с одинаковым содержимым будут ссылаются на один и тот же объект, что объясняет, почему код ниже создает только один объект set, а не три:

```python
set_1 = set([1, 2, 3])  
set_2 = set([1, 2, 3])
set_3 = set([1, 2, 3])

print(set_1 is set_2)  # Output: True
print(set_1 is set_3)  # Output: True
```

Если вам необходимо гарантировать создание нового объекта set при каждом вызове `set()`, можно использовать оператор `{}`:

```python
set_1 = {1, 2, 3}  
set_2 = {1, 2, 3}
set_3 = {1, 2, 3}

print(set_1 is set_2)  # Output: False
print(set_1 is set_3)  # Output: False
```

Также, чтобы обеспечить уникальность объектов при использовании других встроенных типов данных (например, списка `list()`), можно использовать схожий подход - создавать новые объекты через использование оператора `[ ]`:

```python
list_1 = [1, 2, 3]  
list_2 = [1, 2, 3]
list_3 = [1, 2, 3]

print(list_1 is list_2)  # Output: False
print(list_1 is list_3)  # Output: False
```

Более подробную информацию о кэшировании и поведении встроенных объектов в Python можно найти в официальной документации Python.
В вашем примере выражение set() вычисляется один раз, а уже затем вызывается fromkeys. Это не имеет никакого отношения к set, так работают функции почти во всех языках программирования - сначала вычисляются значения аргументов, а потом с этими значениями вызывается функция. Итого, у вас везде передаётся один и тот же объект set. Будь там не set, а какой-нибудь Student, было бы то же самое. 
Правильный вариант: set_dict = { x: set() for x in range(3) }
Надо же, выглядит все это крайне сомнительно. Сеты мутабельные объекты и оптимизация, как c int или str тут не при чем. При том такое поведение только если я создаю объект налету. К примеру  если я соберу их в список например. 

То работает как и ожидается.
Или
Мое мнение крайне сомнительная история.
Похожие вопросы