Теория

Создание новых типов данных в 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) # будет напечатано: "Контакт: Иван"
Задача   2 / 2
1.
В прошлом задании для вывода на экран данных о каждом объекте мы писали отдельный код для каждого объекта. Это громоздко и нерационально, ООП позволяет оптимизировать код.
В классе Contact создайте метод show_contact(), который будет выводить данные любого объекта типа Contact в том же виде, как сейчас их выводит функция print_contact.
  1. В теле класса Contact напишите метод show_contact, который в качестве параметра будет принимать переменную self. В теле метода выполните print(), точно такой же, как в функции print_contact, только вместо имени объекта в аргументе укажите self.
  2. Вызовите метод show_contact для объектов mike и vlad
Удалите из кода функцию print_contact().
Запустите код
Подсказка
  1. В теле класса Contact после функции __init__ объявите функцию: def show_contact(self): В тело этой функции скопируйте любой из вызовов print() из функции print_contact(). В скопированной строке имя конкретного объекта замените на self
  2. Обратиться к методу объекта можно так: имя_объекта.имя_метода()
2.
В прекоде подготовлен класс Planet, он описывает планеты и хранит свойства: name (имя), surface_area (площадь поверхности в км²), average_temp_celcius (средняя температура поверхности планеты по Цельсию), average_temp_fahrenheit (то же по Фаренгейту).
Конструктор класса принимает на вход три параметра: имя планеты, её радиус в километрах и среднюю температуру на поверхности в градусах Цельсия.
  1. В конструкторе вычислите площадь поверхности планеты. Для упрощения считайте планеты сферическими.
Площадь поверхности сферы с радиусом r равна 4 * π * r² . Значение числа π получите так: math.pi (для этого подключите модуль math).
  1. В конструкторе вычислите температуру поверхности по Фаренгейту.
Чтобы перевести температуру по Цельсию в шкалу Фаренгейта, нужно умножить значение на 9/5 и прибавить 32.
Подсказка
  1. В качестве значения свойства self.surface_area подставьте формулу 4 * math.pi * radius * radius
  2. В качестве значения свойства self.average_temp_fahrenheit подставьте формулу temp_celsius * 9 / 5 + 32
Код
Результат