объясните, пожалуйста, код из книги для начинающих

Изучаю сейчас Пайтон, увидела вот такое упр, где нужно понять, что произойдет

import copy
class Car:
    pass

car1 = Car()
car1.wheels = 4
car2 = car1
car2.wheels = 3
print(car1.wheels)  

car3 = copy.copy(car1)
car3.wheels = 6
print(car1.wheels)

сначала я вообще думала, что будет ошибка, ибо в классе Car не определена функция wheels, не понимаю что это такое

вот эта часть тоже не особо понятна, почему выводится 3, а не 4?

car1 = Car()
car1.wheels = 4
car2 = car1
car2.wheels = 3
print(car1.wheels)

Заранее спасибо за ответ.


Ответы (2 шт):

Автор решения: CrazyElf
import copy

class Car:
    pass

Подключена библиотека copy, описан "пустой" класс Car, у которого ничего нет внутри - ни методов, ни полей.

car1 = Car()
car1.wheels = 4

Создали новый объект класса Car, сделали ему новое поле wheels и положили туда значение. Питон - язык динамический, объектам можно "на ходу" добавлять всякие штуки, например, поля (переменные класса).

car2 = car1
car2.wheels = 3
print(car1.wheels)

car2 - ссылка на объект car1, всё, что делается с car2, на самом деле делается с car1, поэтому в car1.wheels будет тоже самое, что в car2.wheels.

car3 = copy.copy(car1)
car3.wheels = 6
print(car1.wheels)

А вот тут car3 - это копия объекта car1, поэтому всё, что делается с объектом car3 уже никак не влияет на объект car1. При копировании объекта новому объекту в момент копирования достаются значения полей старого объекта, но дальше этот новый объект и его поля живут уже своей отдельной жизнью.

→ Ссылка
Автор решения: MarianD

Цель этого кода: Показать вам, что для объектов вообще простое присваивание не создает новый объект — результатом будет только другое имя для того же самого объекта:

car1 = Car()               # Создание нового объекта с именем car1
car1.wheels = 4            # Создание атрибута wheels для него, со значением 4
car2 = car1                # Новое ИМЯ для ТОГО-ЖЕ объекта
car2.wheels = 3            # Изменение атрибута того-же объекта из 4 на 3
print(car1.wheels)         # Проверка того, что объект car1 тот же самый, как объект car2

Другими словами, не надо удивляться над тем, что вы изменили значение атрибута объекта car2 на 3, а тем самым изменился атрибут объекта car1 на 3: car2не другой объект, это только другое имя для car1.


Остальной код показывает, как создать новый объект как копию существующего:

car3 = copy.copy(car1)

и проверка того, что это самостоятельный объект, не зависимый от car1:

car3.wheels = 6         # Изменим значение атрибута wheels объекта car3 на 6 ...
print(car1.wheels)      # ... но атрибут wheels объекта car1 не изменится (остается 3)

В результате:

  • car1, car2: первый объект (с 2 именами),
  • car3: второй объект.
→ Ссылка