Создание новых типов данных в Python

В Python каждая переменная — это объект какого-то класса.
Напишите text = "Война и мир" — и будет создан объект text типа str (строка), обладающий всеми свойствами и методами, присущими классу str.
Код a = 1 создаст объект a типа int: все его свойства и методы описаны в предустановленном классе int.
Если требуется новый класс объектов — разработчик создаёт его: пишет перечень данных и методы для управления данными этого класса.

Создание новых типов данных в Python

Для создания новых классов существует ключевое слово class.
После него указывается имя этого класса. Дальше описывают метод с именем __init__, это специальная функция для создания объектов — конструктор класса. Он вызывается автоматически при создании нового объекта и сохраняет полученные значения в этом объекте.
Синтаксис описания класса выглядит так:
Скопировать кодPYTHON
class <Имя класса>: # конструктор класса — функция с именем __init__ def __init__(self, <параметры конструктора>): # тело метода
Опишем новый класс Contact, предназначенный для хранения контактной информации в записной книжке.
Обратите внимание: код класса пишется с отступом. Все методы внутри блока class пишутся с дополнительными отступами. Забыть об отступах — типичная ошибка новичков. Классам принято давать имена, начинающиеся с заглавной буквы.
Скопировать кодPYTHON
class Contact: def __init__(self, name, phone, birthday): self.name = name self.phone = phone self.birthday = birthday # после создания объекта сообщим об этом print(f"Создан новый контакт {name}") # создадим метод show для вывода на печать данных любого контакта: def show(self): print(f"Имя: {self.name}, телефон: {self.phone}, день рождения: {self.birthday}") # теперь можно создать объект класса Contact, передав в конструктор значения: ivan = Contact(name="Иван", phone="+155512345", birthday="2.12.1985") # а можно использовать сокращённый синтаксис: maria = Contact("Марья", "+277734567", "4.04.1999") # вызовем метод show() для объекта ivan: ivan.show() # будет напечатано: "Имя: Иван, телефон: +155512345, день рождения: 2.12.1985"
Параметр self нужен для того, чтобы объект мог обратиться к собственным методам или свойствам: self.имя_свойства.
Например, строка self.name = name запишет в объект значение свойства name, полученное при вызове конструктора класса. Теперь узнать значение переменной name объекта ivan можно так: ivan.name.
Конструктор класса может не только присваивать значения свойствам, но и вызывать функции прямо в момент создания объекта. В нашем примере конструктор __init__ вызывает функцию print, которая напечатает сообщение о создании нового объекта.
В коде класса помимо __init__ описываются методы — функции, которые могут быть вызваны для работы с объектами этого класса.
У объекта типа Contact описан метод show. Он выводит на экран данные любого объекта типа Contact.

Как напечатать объект

Любая строка и любое число — это объекты, экземпляры классов. Напечатать их на экране — проще простого.
Скопировать кодPYTHON
# при создании экземпляра класса str нет необходимости указывать имя родительского класса # Python сам понимает: раз в кавычках — значит, str. text="Я написать стихи готов, Ребята дорогие, Но не печатаю стихов - Печатают другие." print(text) # будет напечатано: Я написать стихи готов, Ребята дорогие, Но не печатаю стихов - Печатают другие.
Объект text — это экземпляр предустановленного класса str. Объекты ivan да maria — это экземпляры другого класса, Contact. Попробуем напечатать и их, чем они хуже?
Скопировать кодPYTHON
print(ivan) # будет напечатано: <__main__.Contact object at 0x0000021954AE8100> print(maria) # будет напечатано: <__main__.Contact object at 0x0000021954AC4CA0>
Получилось не так красиво, как со строкой: Python вывел на экран имя родительского класса и адрес ячейки памяти, где сохранён объект.
Почему же объект класса str при печати выводит собственное содержимое, а объект класса Contact — только техническую информацию? Хочется короткой командой вывести на экран читаемую информацию об объекте, а не у всякого класса есть метод, подобный методу show().
Решение есть: при описании класса можно указать, как надо интерпретировать его экземпляры, если их пытаются привести к типу str или вывести на печать функцией print().
Для этого есть метод __str__. К этому методу Python обратится, если увидит, что объект пытаются превратить в строку. Если в классе этого метода нет — будет применён стандартный вывод. Именно так и получилось при печати объекта ivan. У предустановленного класса str метод __str__ описан изначально, а в классе Contact его нет.
Исправим ситуацию, допишем в класс Contact метод __str__:
Скопировать кодPYTHON
class Contact: def __init__(self, name, phone, birthday): self.name = name self.phone = phone self.birthday = birthday print(f"Создан новый контакт: «{name}»") def show(self): print(f"Имя: {self.name}, телефон: {self.phone}, день рождения: {self.birthday}") def __str__(self): # можно задать любую строку, например «Не печатай меня, ведь я — объект!», # но лучше пусть при печати выводится осмысленное название объекта и имя return "Контакт: " + self.name # создаём объект: ivan = Contact(name="Иван", phone="+155512345", birthday="2.12.1985") # печатаем объект: print(ivan) # будет напечатано: "Контакт: Иван"