Объекты и классы в Python

В этом руководстве вы познакомитесь с базовым функционалом объектов и классов Python. Что такое класс, как его создать и грамотно использовать в программе.

Python — объектно-ориентированный язык программирования. В отличие от процедурно-ориентированного программирования, ООП опирается на объекты. 

Объект — это набор данных (переменных) и методов (функций), которые с этими данными взаимодействуют. 

Представьте чертеж дома. В нем содержится вся информация: сколько этажей, какого размера двери, окна и т. д. На основе это чертежа мы можем построить дом. Дом — это объект. 

По одному чертежу можно построить сразу несколько домов. Так же и с классом — по нему можно создать много объектов. Объект также можно назвать экземпляром класса, а процесс его создания — инстанцированием.

Как объявить класс

По аналогии с функциями, которые начинаются с def, объявление класса сопровождается ключевым словом class.

Первая строка внутри класса называется строкой документации, в ней содержится краткое описание класса. Писать ее рекомендуется, но не обязательно. 

Объявим класс.

class MyNewClass:
    '''Это строка документации. Мы создали новый класс'''
    pass

Класс создает новое локальное пространство имен, где определяются все атрибуты. Атрибутами могут быть и переменные, и функции.

Есть и специальные атрибуты, которые начинаются с двойного нижнего подчеркивания __. Например, __doc__ — строка документации класса. 

После объявления класса создается объект этого класса с тем же именем. Этот объект класса позволяет нам как получить доступ к различным его атрибутам, так и инстанцировать новые объекты этого класса.

class Person:
    "Это класс, описывающий человека"
    age = 10

    def greet(self):
        print('Привет')

# Вывод: 10
print(Person.age)

# Вывод: <function Person.greet at 0x7f32dbdbeee0>
print(Person.greet)

# Вывод: 'Это мой второй класс'
print(Person.__doc__)

Вывод

10
<function Person.greet at 0x7f32dbdbeee0>
Это класс, описывающий человека

Как создать объект

Мы уже знаем, что объект класса можно использовать для доступа к различным его атрибутам. 

Использовать его можно и для создания новых экземпляров этого класса. Создание объекта похоже на вызов функции. 

>>> harry = Person()

Так мы создадим новый экземпляр класса — harry. Доступ к атрибутам объекта осуществляется при помощи префикса имени объекта. 

Атрибутами могут быть и переменные, и методы. Методы объекта — функции этого класса. 

Это значит следующее: Person.greet — объект функции (атрибут класса), а harry.greet — объект метода

class Person:
    "Это класс, описывающий человека"
    age = 10

    def greet(self):
        print('Привет')


# создаем новый объект класса Person
harry = Person()

# Вывод: <function Person.greet>
print(Person.greet)

# Вывод: <bound method Person.greet of <__main__.Person object>>
print(harry.greet)

# Вызов метода greet() объекта
# Вывод: Привет
harry.greet()

Вывод:

<function Person.greet at 0x7fd288e4e160>
<bound method Person.greet of <__main__.Person object at 0x7fd288e9fa30>>
Привет

Возможно, вы заметили параметр self в функции класса. Но вызывали метод мы с помощью harry.greet(). И почему-то это сработало. 

Так происходит потому, что когда объект вызывает свой метод, сам объект является первым аргументом. То есть harry.greet() это то же самое, что и Person.greet(harry).

Обычно вызов метода со списком аргументов длины n равносилен вызову соответствующей функции со списком аргументов, который создается путем вставки объекта метода перед первым аргументов. 

По этим причинам первый аргумент функции в классе должен быть сам объект. Это и есть self — так договорились программисты на Python. Но в теории можно использовать и другое обозначение.

Теперь вы имеете представление о классах, экземплярах класса, функциях, методах. Главное — понимать их отличия.

Конструкторы

Функции класса, начинающиеся с двойного нижнего подчеркивания, называются специальными функциями

Наибольший интерес вызывает специальная функция __init__(). Она вызывается каждый раз, когда вы создаете новый объект класса. 

В ООП этот вид функций называют конструкторами. Обычно они используются для инициализации всех переменных класса.

class ComplexNumber:
    def __init__(self, r=0, i=0):
        self.real = r
        self.imag = i

    def get_data(self):
        print(f'{self.real}+{self.imag}j')


# Создаем новый объект ComplexNumber 
num1 = ComplexNumber(2, 3)

# Вызываем метод get_data() 
# Вывод: 2+3j
num1.get_data()

# Создаем еще один объект ComplexNumber 
# и новый атрибут 'attr'
num2 = ComplexNumber(5)
num2.attr = 10

# Вывод: (5, 0, 10)
print((num2.real, num2.imag, num2.attr))

# У объекта c1 нет атрибута 'attr', поэтому
# вызывается ошибка
# AttributeError: 'ComplexNumber' object has no attribute 'attr'
print(num1.attr)

Вывод:

2+3j
(5, 0, 10)
Traceback (most recent call last):
 File "<string>", line 27, in <module>
   print(num1.attr)
AttributeError: 'ComplexNumber' object has no attribute 'attr'

В этом примере мы объявили класс, представляющий комплексные числа. В нем две функции. Первая, __init__(), инициализирует переменные (по умолчанию это нули). Вторая, get_data(), позволяет правильно отображать числа в консоли.

Стоит отметить, что атрибуты объекта могут создаваться «на лету». Мы и создали, и считали атрибут attr объекта num2. Но это не значит, что этот атрибут будет доступен num1.

Как удалить атрибуты и объекты

Любой атрибут объекта можно в любой момент удалить. Сделать это можно с помощью оператора del. Попробуйте запустить следующую программу и проверьте, что она выводит.

>>> num1 = ComplexNumber(2,3)
>>> del num1.imag
>>> num1.get_data()
Traceback (most recent call last):
...
AttributeError: 'ComplexNumber' object has no attribute 'imag'
>>> del ComplexNumber.get_data
>>> num1.get_data()
Traceback (most recent call last):
...
AttributeError: 'ComplexNumber' object has no attribute 'get_data'

С помощью del можно удалить даже объект:

>>> c1 = ComplexNumber(1,3)
>>> del c1
>>> c1
Traceback (most recent call last):
...
NameError: name 'c1' is not defined

На самом деле всё намного сложнее. Когда мы выполняем строку c1 = ComplexNumber(1,3), создается новый экземпляр класса. Переменная с1 является ссылкой на него. 

После выполнения команды del c1 ссылка и имя c1 удаляются из соответствующего пространства имен. Однако объект все так же будет существовать. Так что если не связать новую переменную с этим объектом, он позже будет автоматически уничтожен. 

Удаление объектов, на которые нет ссылок, называется сборкой мусора

 

codechick

СodeСhick.io - простой и эффективный способ изучения программирования.

2024 ©