В ООП есть понятие "экземпляр класса". Верно ли оно?

Когда мы создаём класс, у нас как бы появляется шаблон объекта(имею ввиду всё, что написано в отступе 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 шт):

Автор решения: Exci

Возможно путаница у вас возникла из-за некоторой особенности устройства 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, в других языках по-другому, и в общем случае класс - не является никаким объектом, а является просто инструкцией-чертежом.

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

Как обычно, многие особенности Питона объясняются тем, что в нём любая сущность - это объект, причём, "объект первого класса". Класс - это ведь тоже объект, как и экземпляр класса. Вы можете "на лету" менять какие-то поля объекта-класса. Вы и с функциями можете это делать, кстати, и с другими типами объектов, с которыми в других языках обычно нельзя так вот напрямую обращаться и что-то в них менять. Это непривычно после других языков.

Но вернёмся к нашим классам. Ещё раз обозначим особенности Питона:

  • класс - это тоже объект, просто объект типа type
  • вы можете менять многие свойства (атрибуты) объектов "на ходу"
  • когда вы создаёте экземпляр класса, у Питона нет никакого "исходного образца класса", у него есть только вот этот самый объект-класс, у которого вы переопределили некоторые атрибуты
  • когда создаётся объект класса, в него копируются атрибуты класса

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

→ Ссылка