Принадлежность объекта к классу после изменения этого объекта
У нас есть простой класс:
class Test:
n = 5
# Создадим два экземпляра этого класса:
name1 = Test()
name2 = Test()
print(f'{name1.n}, {name2.n}, {Test.n}') # 5, 5, 5
Теперь попробуем изменить один из экземпляров, затем изменим Test.n:
name1.n = 10
print(name1.n) # 10 (Test.n и name2.n на данный момент равны 5)
Test.n = 15 # Изменение самого объекта класса должно повлиять на все ссылки, связанные с ним, но эти изменения не коснуться ссылки name1
print(f'{name1.n}, {name2.n}, {Test.n}') # 10, 15, 15 (соответственно можно предположить, что объект name1 теперь не является объектом класса Test)
#Мы можем проверить принадлежность name1 классу Test:
print(isinstance(name1, Test) # True
Мне объяснили, что этот момент у экземпляра появляется собственный атрибут n, который перекроет (переопределит) родительский, то есть тот, который достался от класса. Но тогда не ясно, почему:
> print(isinstance(name1, Test) # True
Я предполагаю, что на самом деле у нас теперь есть два экземпляра класса Test с одинаковым именем - на первый ссылается name1, на второй ссылается name2. И когда мы пишем Test.n питон работает именно с тем экземпляром на который ссылается name2. Если это так, то где определяется структура экземпляра Test на который ссылается name1? Мы же по сути можем создать в этом экземпляре свои атрибуты, и единственная возможность получить к нему доступ - это через ссылку name1 :
name1.l = 24
В конце концов он может не иметь ничего общего по структуре с классом Test, может для таких объектов без шаблона есть своё название? В общем буду признателен, если просветите, ну либо укажете на то, что я тут несу чушь)
Ответы (1 шт):
class Test:
n = 5
n - доступен для всех экземпляров, которые его не переопределяли.
name1 = Test()
name2 = Test()
name1.n = 10
name1.n
- тут уже n локальный атрибут.
- Когда мы изменяем атрибут конкретного экземпляра Test(). То у этого экземпляра переопределяется ссылка на атрибут n. То есть мы перестаем ссылаться на атрибут определённый на уровне класса.
- Когда изменяется атрибут самого класса
Test.n = 15
, это влияет на все его экземпляры, которые не переопределили этот атрибут локально. А всё потому, что n продолжает ссылаться наTest.n = 15
даже при создании экземпляраname1 = Test()
При этом, даже если мы переопределим в экземпляре атрибут n, то мы всё равно сможем получить к нему доступ:
class Test:
n = 5
def get_n(self):
print(self.n) # name.n
print(Test.n)
print(self.__class__.n) # name.__class__.n
print(type(self).n) # type(name).n
name = Test()
name.n = 15
name.get_n()
Вывод:
15
5
5
5
isinstance(name, Test)
возвращает True - потому что name всё ещё является экземпляром класса Test и был создан на его основе. Даже если перевести метод isinstance - получим перевод это экземпляр, что собственно намекает?
Отсюда делаем вывод, что экземпляр name может иметь свои локальные атрибуты, определять их или переопределять и при этом оставаться экземпляром класса на основе которого был создан.