Переменные экземпляра
Как правило, класс может иметь два различных типа данных для формирования свойств класса. Вы уже видели один из них, когда мы смотрели на стеки.
Такое свойство класса существует тогда и только тогда, когда оно явно создано и добавлено в объект. Как Вы уже знаете, это можно сделать во время инициализации объекта, выполняемой конструктором.
Более того, это можно сделать в любой момент жизни объекта. Кроме того, любое существующее свойство может быть удалено в любое время.
Такой подход имеет некоторые важные последствия:
- разные объекты одного и того же класса могут обладать разными наборами свойств;
- должен быть способ безопасно проверить, принадлежит ли конкретному объекту свойство, которое Вы хотите использовать (если Вы не хотите вызывать исключение - это всегда стоит учитывать);
- каждый объект несет свой собственный набор свойств - они никоим образом не мешают друг другу.
Такие переменные (свойства) называются переменными экземпляра.
Слово instance (экземпляр) предполагает, что они тесно связаны с объектами (которые являются экземплярами классов), а не с самими классами. Давайте внимательнее посмотрим на них.
Вот пример:
class ExampleClass:
def __init__(self, val = 1):
self.first = val
def set_second(self, val):
self.second = val
example_object_1 = ExampleClass()
example_object_2 = ExampleClass(2)
example_object_2.set_second(3)
example_object_3 = ExampleClass(4)
example_object_3.third = 5
print(example_object_1.__dict__)
print(example_object_2.__dict__)
print(example_object_3.__dict__)
Требуется одно дополнительное объяснение, прежде чем мы углубимся в детали. Посмотрите на последние три строки кода.
Объекты Python, когда они создаются, получают небольшой набор предопределенных свойств и методов. Каждый объект имеет их, хотите ли Вы их или нет. Одной из них является переменная с именем __dict__
(это словарь).
Переменная содержит имена и значения всех свойств (переменных), которые несет объект в настоящее время. Давайте использовать его для безопасного представления содержимого объекта.
Давайте сейчас углубимся в код:
- класс с именем
ExampleClass
имеет конструктор, который безоговорочно создает переменную экземпляра с именемfirst
и устанавливает его со значением, пропущенным через первый аргумент (с точки зрения пользователя класса) или второй аргумент (с точки зрения конструктора); обратите внимание на значение параметра по умолчанию - любой метод, который Вы можете сделать с обычным параметром функции, может быть применен и к методам; - у класса также есть метод, который создает другую переменную экземпляра с именем
second
; - мы создали три объекта класса
ExampleClass
, но все эти экземпляры различаются: exampleObject1
только имеет свойство с именемfirst
;exampleObject2
имеет два свойства:first
иsecond
;exampleObject3
был расширен свойством с именемthird
просто налету, вне кода класса - это возможно и полностью допустимо.
Вывод программы ясно показывает, что наши предположения верны:
{'first': 1}
{'second': 3, 'first': 2}
{'third': 5, 'first': 4}
output
Здесь следует сделать один дополнительный вывод: изменение переменной экземпляра любого объекта не влияет на все остальные объекты. Переменные экземпляра идеально изолированы друг от друга.