Конструктор и метод класса в Python: создание объектов и инициализация

0
47

Краткая памятка по созданию объектов в Python

  1. Определите класс с помощью ключевого слова class.
  2. Реализуйте метод __init__ для инициализации атрибутов.
  3. Используйте self для доступа к атрибутам экземпляра.
  4. Создайте объект, вызвав класс с аргументами: MyClass(args).
  5. Примените инкапсуляцию для защиты данных.
  6. Используйте наследование для расширения функциональности.
  7. Переопределяйте методы для изменения поведения.
  8. Применяйте полиморфизм для работы с разными классами.
  9. Удаляйте объекты с помощью del или сборщика мусора.
  10. Используйте свойства (property) для управления доступом.
  11. Определяйте приватные атрибуты с двойным подчеркиванием.
  12. Изучите встроенные атрибуты класса, такие как __doc__.

Создание классов и объектов

Программирование на - изображение номер один
Программирование на — изображение номер один

Для того чтобы создать объект класса необходимо воспользоваться следующим синтаксисом:

Методы класса

26 - изображение номер два
26 — изображение номер два

Добавим к нашему классу метод. Метод – это функция, находящаяся внутри класса и выполняющая определенную работу.

Методы бывают статическими, классовыми (среднее между статическими и обычными) и уровня класса (будем их называть просто словом метод). Статический метод создается с декоратором @staticmethod, классовый – с декоратором @classmethod, первым аргументом в него передается cls, обычный метод создается без специального декоратора, ему первым аргументом передается self:

Статический и классовый метод можно вызвать, не создавая экземпляр класса, для вызова ex_method() нужен объект:

>>> MyClass.ex_static_method() static method >>> MyClass.ex_class_method() class method >>> MyClass.ex_method() Traceback (most recent call last): File «<stdin>», line 1, in <module> TypeError: ex_method() missing 1 required positional argument: ‘self’ >>> m = MyClass() >>> m.ex_method() method

Поддержка получения произвольных атрибутов методами.

Курс по - изображение номер три
Курс по — изображение номер три

Связанные методы имеют два специальных атрибута, доступных только для чтения: m.__ self__ — это объект, с которым работает метод, и m.__func__ — это функция, реализующая метод. Вызов m(arg-1, arg-2,…, arg-n) полностью эквивалентен вызову m.__func__(m.__self__, arg-1, arg-2,…, arg-n).

Как и объекты функций, связанные объекты методов поддерживают получение произвольных атрибутов. Однако, поскольку атрибуты метода фактически хранятся в базовом объекте функции (meth.__func__), то установка атрибутов метода для связанных методов запрещена. Попытка установить атрибут в методе приводит к возникновению исключения AttributeError. Чтобы установить атрибут метода, необходимо явно установить его для базового объекта функции:

>>> class C:… def method(self):… pass… >>> c = C() >>> = ‘my name is method’ # can’t set on the method # Traceback (most recent call last): # File «<stdin>», line 1, in <module> # AttributeError: ‘method’ object has no attribute ‘whoami’ >>>.__func__.whoami = ‘my name is method’ >>> # ‘my name is method’

Конструктор класса и инициализация экземпляра класса

Python - изображение номер четыре
Python — изображение номер четыре

В Python разделяют конструктор класса и метод для инициализации экземпляра класса. Конструктор класса это метод __new__(cls, *args, **kwargs) для инициализации экземпляра класса используется метод __init__(self). При этом, как вы могли заметить __new__ – это классовый метод, а __init__ таким не является. Метод __new__ редко переопределяется, чаще используется реализация от базового класса object (см. раздел Наследование), __init__ же наоборот является очень удобным способом задать параметры объекта при его создании.

Создадим реализацию класса Rectangle с измененным конструктором и инициализатором, через который задается ширина и высота прямоугольника:

class Rectangle: def __new__(cls, *args, **kwargs): print(«Hello from __new__») return super().__new__(cls) def __init__(self, width, height): print(«Hello from __init__») = width = height >>> rect = Rectangle(10, 20) Hello from __new__ Hello from __init__ >>> 10 >>> 20

Что такое self?

What is - изображение номер пять
What is — изображение номер пять

До этого момента вы уже успели познакомиться с ключевым словом self. self – это ссылка на текущий экземпляр класса, в таких языках как Java, C# аналогом является ключевое слово this. Через self вы получаете доступ к атрибутам и методам класса внутри него:

В приведенной реализации метод area получает доступ к атрибутам width и height для расчета площади. Если бы в качестве первого параметра не было указано self, то при попытке вызвать area программа была бы остановлена с ошибкой.

Создание экземпляров класса

Объектно-ориентированное программирование на python - online presentation - изображение номер шесть
Объектно-ориентированное программирование на python — online presentation — изображение номер шесть

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

Доступ к атрибутам

Archy \ - изображение номер семь
Archy \ — изображение номер семь

Получите доступ к атрибутам класса, используя оператор. после объекта класса. Доступ к классу можно получить используя имя переменой класса:

class Employee: «»»Базовый класс для всех сотрудников»»» emp_count = 0 def __init__(self, name, salary): = name = salary Employee.emp_count += 1 def display_count(self): print(‘Всего сотрудников: %d’ % Employee.emp_count) def display_employee(self): print(‘Имя: {}. Зарплата: {}’.format(,)) emp1 = Employee(«Андрей», 2000) emp2 = Employee(«Мария», 5000) emp1.display_employee() emp2.display_employee() print(«Всего сотрудников: %d» % Employee.emp_count)

Вместо использования привычных операторов для доступа к атрибутам вы можете использовать эти функции:

  • getattr(obj, name [, default]) — для доступа к атрибуту объекта.
  • hasattr(obj, name) — проверить, есть ли в obj атрибут name.
  • setattr(obj, name, value) — задать атрибут. Если атрибут не существует, он будет создан.
  • delattr(obj, name) — удалить атрибут.

hasattr(emp1, ‘age’) getattr(emp1, ‘age’) setattr(emp1, ‘age’, 8) delattr(empl, ‘age’)

Встроенные атрибуты класса

Классы и итераторы - презентация онлайн - изображение номер восемь
Классы и итераторы — презентация онлайн — изображение номер восемь

Каждый класс Python хранит встроенные атрибуты, и предоставляет к ним доступ через оператор., как и любой другой атрибут:

  • __dict__ — словарь, содержащий пространство имен класса.
  • __doc__ — строка документации класса. None если, документация отсутствует.
  • __name__ — имя класса.
  • __module__ — имя модуля, в котором определяется класс. Этот атрибут __main__ в интерактивном режиме.
  • __bases__ — могут быть пустые tuple, содержащие базовые классы, в порядке их появления в списке базового класса.
ЧИТАТЬ ТАКЖЕ:  Что такое from import в Python 3: основы работы импортов, абсолютный и относительный импорт, отличие от from import, ошибки импорта

Для вышеуказанного класса давайте попробуем получить доступ ко всем этим атрибутам:

class Employee: «»»Базовый класс для всех сотрудников»»» emp_count = 0 def __init__(self, name, salary): = name = salary += 1 def display_count(self): print(‘Всего сотрудников: %d’ %) def display_employee(self): print(‘Имя: {}. Зарплата: {}’.format(,)) print(«Employee.__doc__:», Employee.__doc__) print(«Employee.__name__:», Employee.__name__) print(«Employee.__module__:», Employee.__module__) print(«Employee.__bases__:», Employee.__bases__) print(«Employee.__dict__:», Employee.__dict__)

Удаление объектов (сбор мусора)

Жизненный цикл - изображение номер девять
Жизненный цикл — изображение номер девять

Python автоматически удаляет ненужные объекты (встроенные типы или экземпляры классов), чтобы освободить пространство памяти. С помощью процесса ‘Garbage Collection’ Python периодически восстанавливает блоки памяти, которые больше не используются.

Сборщик мусора Python запускается во время выполнения программы и тогда, когда количество ссылок на объект достигает нуля. С изменением количества обращений к нему, меняется количество ссылок.

Когда объект присваивают новой переменной или добавляют в контейнер (список, кортеж, словарь), количество ссылок объекта увеличивается. Количество ссылок на объект уменьшается, когда он удаляется с помощью del, или его ссылка выходит за пределы видимости. Когда количество ссылок достигает нуля, Python автоматически собирает его.

Обычно вы не заметите, когда сборщик мусора уничтожает экземпляр и очищает свое пространство. Но классом можно реализовать специальный метод __del__(), называемый деструктором. Он вызывается, перед уничтожением экземпляра. Этот метод может использоваться для очистки любых ресурсов памяти.

Пример работы __del__()Деструктор __del__() выводит имя класса того экземпляра, который должен быть уничтожен:

class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print(‘{} уничтожен’.format(class_name)) pt1 = Point() pt2 = pt1 pt3 = pt1 print(id(pt1), id(pt2), id(pt3)) del pt1 del pt2 del pt3

В идеале вы должны создавать свои классы в отдельном модуле. Затем импортировать их в основной модуль программы с помощью import SomeClass.

Уровни доступа атрибута и метода

6 - изображение номер десять
6 — изображение номер десять

Если вы знакомы с языками программирования Java, C#, C++ то, наверное, уже задались вопросом: “а как управлять уровнем доступа?”. В перечисленных языка вы можете явно указать для переменной, что доступ к ней снаружи класса запрещен, это делается с помощью ключевых слов (private, protected и т.д.). В Python таких возможностей нет, и любой может обратиться к атрибутам и методам вашего класса, если возникнет такая необходимость. Это существенный недостаток этого языка, т.к. нарушается один из ключевых принципов ООП – инкапсуляция. Хорошим тоном считается, что для чтения/изменения какого-то атрибута должны использоваться специальные методы, которые называются getter/setter, их можно реализовать, но ничего не помешает изменить атрибут напрямую. При этом есть соглашение, что метод или атрибут, который начинается с нижнего подчеркивания, является скрытым, и снаружи класса трогать его не нужно (хотя сделать это можно).

class Rectangle: def __init__(self, width, height): self._width = width self._height = height def get_width(self): return self._width def set_width(self, w): self._width = w def get_height(self): return self._height def set_height(self, h): self._height = h def area(self): return self._width * self._height

В приведенном примере для доступа к _width и _height используются специальные методы, но ничего не мешает вам обратиться к ним (атрибутам) напрямую.

Если же атрибут или метод начинается с двух подчеркиваний, то тут напрямую вы к нему уже не обратитесь (простым образом). Модифицируем наш класс Rectangle:

class Rectangle: def __init__(self, width, height): self.__width = width self.__height = height def get_width(self): return self.__width def set_width(self, w): self.__width = w def get_height(self): return self.__height def set_height(self, h): self.__height = h def area(self): return self.__width * self.__height

>>> rect = Rectangle(10, 20) >>> rect.__width Traceback (most recent call last): File «<stdin>», line 1, in <module> AttributeError: ‘Rectangle’ object has no attribute ‘__width’ >>> rect.get_width() 10

Но на самом деле это сделать можно, просто этот атрибут теперь для внешнего использования носит название: _Rectangle__width:

Приватные методы и атрибуты

Learn - изображение номер одиннадцать
Learn — изображение номер одиннадцать

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

class JustCounter: __secret_count = 0 def count(self): self.__secret_count += 1 print(self.__secret_count) counter = JustCounter() () () print(counter.__secret_count)

Вы можете получить доступ к таким атрибутам, так object._className__attrName. Если вы замените свою последнюю строку следующим образом, то она будет работать.

Свойства

Полезные ресурсы для изучения - изображение номер двенадцать
Полезные ресурсы для изучения — изображение номер двенадцать

Свойством называется такой метод класса, работа с которым подобна работе с атрибутом. Для объявления метода свойством необходимо использовать декоратор @property.

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

class Rectangle: def __init__(self, width, height): self.__width = width self.__height = height @property def width(self): return self.__width @ def width(self, w): if w > 0: self.__width = w else: raise ValueError @property def height(self): return self.__height @ def height(self, h): if h > 0: self.__height = h else: raise ValueError def area(self): return self.__width * self.__height

Если вы обратили внимание: в setter’ах этих свойств осуществляется проверка входных значений, если значение меньше нуля, то будет выброшено исключение ValueError:

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

class Figure: def __init__(self, color): self.__color = color @property def color(self): return self.__color @ def color(self, c): self.__color = c class Rectangle(Figure): def __init__(self, width, height, color): super().__init__(color) self.__width = width self.__height = height @property def width(self): return self.__width @ def width(self, w): if w > 0: self.__width = w else: raise ValueError @property def height(self): return self.__height @ def height(self, h): if h > 0: self.__height = h else: raise ValueError def area(self): return self.__width * self.__height

ЧИТАТЬ ТАКЖЕ:  Блок схема по коду Python: как сделать, примеры и инструменты

Родительским классом является Figure, который при инициализации принимает цвет фигуры и предоставляет его через свойства. Rectangle – класс наследник от Figure. Обратите внимание на его метод __init__: в нем первым делом вызывается конструктор (хотя это не совсем верно, но будем говорить так) его родительского класса:

super – это ключевое слово, которое используется для обращения к родительскому классу.

Теперь у объекта класса Rectangle помимо уже знакомых свойств width и height появилось свойство color:

Как уже было сказано во введении в рамках ООП полиморфизм, как правило, используется с позиции переопределения методов базового класса в классе наследнике. Проще всего это рассмотреть на примере. Добавим в наш базовый класс метод info(), который печатает сводную информацию по объекту класса Figure и переопределим этот метод в классе Rectangle, добавим в него дополнительные данные:

class Figure: def __init__(self, color): self.__color = color @property def color(self): return self.__color @ def color(self, c): self.__color = c def info(self): print(«Figure») print(«Color: » + self.__color) class Rectangle(Figure): def __init__(self, width, height, color): super().__init__(color) self.__width = width self.__height = height @property def width(self): return self.__width @ def width(self, w): if w > 0: self.__width = w else: raise ValueError @property def height(self): return self.__height @ def height(self, h): if h > 0: self.__height = h else: raise ValueError def info(self): print(«Rectangle») print(«Color: » +) print(«Width: » + str()) print(«Height: » + str()) print(«Area: » + str(())) def area(self): return self.__width * self.__height

Наследование

Объектно-ориентированное программирование на - изображение номер тринадцать
Объектно-ориентированное программирование на — изображение номер тринадцать

Наследование — это процесс, когда один класс наследует атрибуты и методы другого. Класс, чьи свойства и методы наследуются, называют Родителем или Суперклассом. А класс, свойства которого наследуются — класс-потомок или Подкласс.

Вместо того, чтобы начинать с нуля, вы можете создать класс, на основе уже существующего. Укажите родительский класс в круглых скобках после имени нового класса.

Класс наследник наследует атрибуты своего родительского класса. Вы можете использовать эти атрибуты так, как будто они определены в классе наследнике. Он может переопределять элементы данных и методы родителя.

Синтаксис наследования класса

Классы наследники объявляются так, как и родительские классы. Только, список наследуемых классов, указан после имени класса.

Пример наследования класса в Python

Наследование, полиморфизм в - изображение номер пятнадцать
Наследование, полиморфизм в — изображение номер пятнадцать

class Parent: parent_attr = 100 def __init__(self): print(‘Вызов родительского конструктора’) def parent_method(self): print(‘Вызов родительского метода’) def set_attr(self, attr): Parent.parent_attr = attr def get_attr(self): print(‘Атрибут родителя: {}’.format(Parent.parent_attr)) class Child(Parent): def __init__(self): print(‘Вызов конструктора класса наследника’) def child_method(self): print(‘Вызов метода класса наследника’) c = Child() c.child_method() c.parent_method() c.set_attr(200) c.get_attr()

Аналогичным образом вы можете управлять классом с помощью нескольких родительских классов:

Вы можете использовать функции issubclass() или isinstance() для проверки отношений двух классов и экземпляров.

  • Логическая функция issubclass(sub, sup) возвращает значение True, если данный подкласс sub действительно является подклассом sup.
  • Логическая функция isinstance(obj, Class) возвращает True, если obj является экземпляром класса Class или является экземпляром подкласса класса.

Переопределение методов

How are method default arguments overridden in python? - изображение номер шестнадцать
How are method default arguments overridden in python? — изображение номер шестнадцать

Вы всегда можете переопределить методы родительского класса. В вашем подклассе могут понадобиться специальные функции. Это одна из причин переопределения родительских методов.

class Parent: def my_method(self): print(‘Вызов родительского метода’) class Child(Parent): def my_method(self): print(‘Вызов метода наследника’) c = Child() c.my_method()

Полиморфизм

Полиморфизм позволяет одинаково обращаться с объектами, имеющими однотипный интерфейс, независимо от внутренней реализации объекта. Например, с объектом класса “грузовой автомобиль” можно производить те же операции, что и с объектом класса “автомобиль”, т.к. первый является наследником второго, при этом обратное утверждение неверно (во всяком случае не всегда). Другими словами полиморфизм предполагает разную реализацию методов с одинаковыми именами. Это очень полезно при наследовании, когда в классе наследнике можно переопределить методы класса родителя.

Популярные базовые методы

classmethod and staticmethod - изображение номер восемнадцать
classmethod and staticmethod — изображение номер восемнадцать

В данной таблице перечислены некоторые общие функции. Вы можете переопределить их в своих собственных классах.

Таблица №1

Метод, описание и пример вызова
1 __init__(self [, args...]) — конструктор (с любыми необязательными аргументами)
obj = className(args)
2 __del__(self) — деструктор, удаляет объект
del obj
3 __repr__(self) — программное представление объекта
repr(obj)
4 __str__(self) — строковое представление объекта
str(obj)

Пример использования __add__

ООП - изображение номер девятнадцать
ООП — изображение номер девятнадцать

Предположим, вы создали класс Vector для представления двумерных векторов. Что происходит, когда вы используете дополнительный оператор для их добавления? Скорее всего, Python будет против.

Однако вы можете определить метод __add__ в своем классе для добавления векторов и оператор + будет вести себя так как нужно.

class Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return ‘Vector ({}, {})’.format(self.a, self.b) def __add__(self, other): return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2, 10) v2 = Vector(5, -2) print(v1 + v2)

P.S.

Если вам интересна тема анализа данных, то мы рекомендуем ознакомиться с библиотекой Pandas. На нашем сайте вы можете найти вводные уроки по этой теме.
Все уроки по библиотеке Pandas собраны в книге “Pandas. Работа с данными”.

Урок 9 - изображение номер двадцать
Урок 9 — изображение номер двадцать

Часто задаваемые вопросы о методах создания объектов в Python

Вопрос: Какой метод класса в Python создает объект?
Ответ: Объект создается с помощью конструктора __init__, который вызывается автоматически при создании экземпляра класса.

Вопрос: В чем разница между __new__ и __init__?
Ответ: __new__ создает новый объект, а __init__ инициализирует его атрибуты.

Вопрос: Обязательно ли определять __init__ в классе?
Ответ: Нет, если не требуется инициализация, Python создаст объект без него.

Вопрос: Можно ли создать объект без вызова конструктора?
Ответ: Да, через __new__ напрямую, но это редко используется.

Вопрос: Как передать аргументы в конструктор класса?
Ответ: Через параметры метода __init__, например: def __init__(self, name).

Вопрос: Что такое self в конструкторе?
Ответ: self — ссылка на текущий экземпляр класса, передается автоматически.

Вопрос: Может ли конструктор возвращать значение?
Ответ: Нет, __init__ должен возвращать None.

Вопрос: Как создать объект с атрибутами по умолчанию?
Ответ: Задать значения в __init__ через параметры по умолчанию.

Вопрос: Что произойдет, если не определить __init__?
Ответ: Python использует конструктор по умолчанию, который не инициализирует атрибуты.

Вопрос: Как вызвать конструктор родительского класса?
Ответ: Через super().__init__() в дочернем классе.