В ООП есть понятие "экземпляр класса". Верно ли оно?
Когда мы создаём класс, у нас как бы появляется шаблон объекта(имею ввиду всё, что написано в отступе class), и сам оригинальный объект, который доступен по имени класса(имя класса является ссылкой на этот оригинальный объект):
class InCap:
name = 10
InCap.name = 203 #мы можем убедиться в существовании оригинального объекта, сразу изменив его атрибут
print(InCap.name) # Вывод : 203
В курсах и учебных материалах(по крайней в тех по которым учусь я) говорится, что мы можем создать экземпляр класса, однако выходит, что мы создаём экземпляр оригинального объекта, а не класса т.к. все атрибуты и родительские(те, что описаны в шаблоне класса) и локальные(те, что мы можем добавить в наш оригинал) по умолчанию наследуются экземплярами :
Namer = InCap() #создали экземпляр оригинального объекта
# Добавим в оригинальный объект новый атрибут:
InCap.Unname = 30
print(f'новый атрибут оригинального объекта: {Namer.Unname}, родительский атрибут оригинального объекта: {Namer.Name}')
# Вывод: новый атрибут оригинального объекта: 30, родительский атрибут оригинального объекта: 203
Мы видим, что экземпляр наследует от оригинального объекта атрибуты Name и Unname(а не от класса, в котором атрибута Unname нет), и это будет происходит только до тех пор, пока мы их не переопределим :
Namer.Unname = 'переопределили'
Namer.Name = 'переопределили'
print(Namer.Unname, Namer.Name)# Вывод: переопределили переопределили Теперь это локальные атрибуты.
print(InCap.Name, InCap.Unname)# Вывод: 203 30
Атрибуты оригинального объекта остаются прежними, изменения над ними не коснуться локальных:
print(Namer.Unname, Namer.Name)
print(InCap.Name, InCap.Unname)
# Вывод:
# переопределили переопределили
# изменили изменили
Резюмируя, ни разу не слышал о создании экземпляра оригинального объекта и наследовании атрибутов от такового, везде экземпляры класса, а по факту выходит, что шаблон тут не причём и такая формулировка приводит к путанице, по крайней мере меня. В общем, буду рад, если подтвердите или опровергните мои догадки, заранее спасибо за ответ.
Ответы (2 шт):
Возможно путаница у вас возникла из-за некоторой особенности устройства python, вообще говоря для большинства языков не характерно то, что мы можем обращаться с классом как с объектом. В ООП, если понимать его вне контекста языка python, класс это просто инструкция-шаблон для будущих объектов, по этой инструкции компилятор или интерпретатор создают объекты - выделяют память, размещают код методов и их адреса и т.д. Это скажем так классический взгляд на классы. Оттуда и пошло понятие "экземпляр класса", то же что и "объект класса" - объект созданный по шаблону данного класса. Особенность python - то что классы сразу как мы их объявили - сами являются объектами(они, кстати, являются объектами другого класса - их метакласса). Но в литературе если вы читаете "объект класса" - следует понимать в классическом смысле(может быть если только это не глава посвященная пониманию классов как самостоятельных объектов в python). Посмотреть какому классу принадлежит объект можно через поле class:
class Foo:
n = 1
f = Foo()
print(Foo.__class__)
print(f.__class__)
Этот код выведет:
<class 'type'>
<class '__main__.Foo'>
Потому что Foo является объектом класса type - это общий метакласс по-умолчанию для всех объектов, а f является объектом Foo.
Просто стоит держать в голове что такая система это особенность конкретно языка python, в других языках по-другому, и в общем случае класс - не является никаким объектом, а является просто инструкцией-чертежом.
Как обычно, многие особенности Питона объясняются тем, что в нём любая сущность - это объект, причём, "объект первого класса". Класс - это ведь тоже объект, как и экземпляр класса. Вы можете "на лету" менять какие-то поля объекта-класса. Вы и с функциями можете это делать, кстати, и с другими типами объектов, с которыми в других языках обычно нельзя так вот напрямую обращаться и что-то в них менять. Это непривычно после других языков.
Но вернёмся к нашим классам. Ещё раз обозначим особенности Питона:
- класс - это тоже объект, просто объект типа
type
- вы можете менять многие свойства (атрибуты) объектов "на ходу"
- когда вы создаёте экземпляр класса, у Питона нет никакого "исходного образца класса", у него есть только вот этот самый объект-класс, у которого вы переопределили некоторые атрибуты
- когда создаётся объект класса, в него копируются атрибуты класса
Ну то есть да. Всё так, как вы отметили, и это совершенно логично с точки зрения Питона. В принципе, теоретически, создатели языка могли бы вести два отдельных списка атрибутов объектов - те, которые вы задали исходным кодом программы, и те, которые вы добавили уже в ходе выполнения программы. Но в Питоне такого нет, в нём все сущности живут динамической жизнью и никто не следит, на каком этапе у объекта появились те или иные атрибуты.