0 знаков
66. Разбираемся с атрибутами и методами класса в Python
В предыдущем уроке мы реализовали два класса User и Admin, создали конструктор, добавили атрибуты и методы класса, перегрузили оператор и попробовали наследовать Admin от User. В этом уроке более детально поговорим о реализации оператора class, атрибутах и методах в Python.
Оператор class
Например, как и в C++, оператор class представляет собой главный инструмент ООП в Python, но в отличие от C++ оператор class языка Python class не является объявлением. Подобно def оператор class создает объекты и неявно присваивает их - при выполнении он генерирует объект класса и сохраняет ссылку на него в имени, используемом в заголовке.
Также подобно def оператор class относится к настоящему исполняемому коду - ваш класс не существует до тех пор, пока Python не достигнет и не выполнит оператор class, который его определяет. Обычно это происходит во время импортирования модуля, содержащего оператор class, но не ранее.
Общая форма оператора class:
class имя(суперкласс, ...):
атрибут = значение
def метод(self, ...):
self.атрибут = значение Оператор class определяет пространство имен. Он напоминает как модули (подобно именам в модуле имена, присвоенные в операторе class, становятся атрибутами в объекте класса), так и функции (подобно функциям операторы class являются локальными областями видимости, где находятся имена, созданные вложенными присваиваниями).
Зачем тогда использовать классы, если они вбирают в себя возможности модулей и функций? Пространство имен классов формирует основу для наследования в Python. Используемые атрибуты, отсутствующие в объекте класса, извлекаются из других классов, от которых он наследуется.
Атрибуты класса
Присвоение значений простым объектам (не функциям) создают атрибуты класса:
class TestClass:
a = 10 # атрибут класса
x = TestClass() # первый экземпляр класса
y = TestClass() # второй экземпляр класса
print(x.a, y.a) # => 10 10 Чтобы изменить значение атрибута для всех экземпляров класса, необходимо обратиться к этому атрибуту через имя класса:
TestClass.a = 100
print(x.a, y.a) # => 100 100 Что если менять значение через экземпляр? Посмотрим на примере:
x.a = 99
print(x.a, y.a) # => 99 10 Далее рассмотрим пример поведения атрибутов класса и экземпляра:
class TestClass:
data = 'atr'
def __init__(self, value):
self.data = value
def display(self):
print(f'Атрибут экземпляра: {self.data}',
f'Атрибут класса: {TestClass.data}')
x = TestClass(1)
y = TestClass(2)
x.display() # => 1 atr
y.display() # => 2 atr Значение имени data находится в локальной области видимости класса и поэтому становится атрибутом класса, который разделяется всеми экземплярами класса. Атрибут data присутствует в двух местах: в локальной области видимости класса и в конструкторе (в __init__()).
Методы класса
Метод класса является обычной функцией, в дополнении к последней имеет аргумент self (через него метод получает объект экземпляра) и находится в области видимости класса, в котором объявлен. То есть следующий вызов метода display() из предыдущего примера:
x.display() # => 1 atr Интерпретатор Python преобразует в следующий вид:
TestClass.display(x) # => 1 atr Рассмотрим еще один пример метода класса в Python:
class TestClass:
def display(self, text):
self.data = text
print(self.data)
x = TestClass()
x.display(123) # => 123
print(x.data) # => 123 Имя display ссылается на объект функции (def) и находится в области видимости оператора class, тем самым является методом класса, который наследуется всеми экземплярами, созданным из класса. Когда мы вызываем метод следующим способом x.display(123), метод display сначала ищется в иерархии наследования и затем интерпретатор Python автоматически присваивает аргументу self объект экземпляра x. Далее разберемся для чего может пригодиться вызывать метод через имя класса, а не экземпляра.
Вызов метода через имя класса
Могла показаться ненужность вызова метода через класс:
TestClass.display(x) Однако такой подход полезен в некоторых случаях: конструктор __init__. На стадии конструирования интерпретатор Python ищет только один метод __init__ в иерархии наследования. Если нужна гарантия вызова подклассом (в примере SubClass) конструктора суперкласса (в примере SuperClass), то конструктор __init__ суперкласса нужно вызывать явно через имя класса:
class SuperClass:
def __init__(self, x) -> None:
pass
class SubClass(SuperClass):
def __init__(self, x, y) -> None:
SuperClass.__init__(self, x)
pass
x = SubClass(2, 3) Думаю после этого урока вы уже полностью разобрались с атрибутами и методами классов Python. В следующем уроке еще раз поговорим про наследование и познакомимся с абстрактными суперклассами.
Тест
Похожие уроки Codebra
Подписывайся на наш Telegram-канал!
Новости, полезный материал,
программирование и ИБ
Подписывайся на наш Telegram-канал!
Новости, полезный материал,
программирование и ИБ