Уроки Питон №16/20. Объектная модель (sq = [i**2 for i in range(1, 6)]) в Питон

Урок 20. Объектная модель в Python

В рамках данного урока поговорим об объектной модели Python: в чем ее особенность и как ее можно использовать в своей работе.

Что такое объектная модель Python?

Самым лаконичным ответом на вопрос: “что такое объектная модель Python“, будет цитата из википедии, которую также приводит в своей книге Лучано Рамальо: the properties of objects in general in a specific computer programming language, technology, notation or methodology that uses them. Что можно перевести как “общие свойства объектов в конкретном языке программирования, технологии, нотации или методологии”.

Красота объектной модели в Python состоит в том, что если на уровне класса реализовать определенный функционал, то с объектами этого класса можно будет работать используя “питонический стиль” – стиль написания программного кода на Python, который отличается большей выразительностью, читаемостью и понятностью. Такой стиль называют идиоматический – использующий наиболее естественные для данного языка решения.

Для того, чтобы понять о чем идет речь, рассмотрим пример: списковое включение (list comprehensions).

Напишем код, который создает список из квадратов первых пять целых чисел:

sq = []

for i in range(1, 6):

sq.append(i**2)

Теперь напишем этот же код с использованием спискового включения:

sq = [i**2 for i in range(1, 6)]

Не правда ли, второй вариант более лаконичный, красивый и понятный? (Хотя мы не отрицаем, что возможно есть люди, которым больше нравится первый вариант).

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

Синонимом “объектной модели” является “модель данных”. В Python документации есть целый раздел, посвященный этой теме https://docs.python.org/3/reference/datamodel.html.

Специальные методы

Рассмотрим некоторые из специальных методов (самые интересные, как нам показалось). Более подробную информацию о них вы можете найти в соответствующей документации по Python.

__repr__()

Строковое представление объекта, позволяющее восстановить объект. Например, если вы пишете игру и у вас есть объект “Персонаж”, которому при его создании присваивается имя и пол, то метод __repr__() может вернуть следующую строку “Person(“John”, “man”)”.  Эта информация позволит вам заново построить объект.

__str__()

Строковое представление объекта, используемое в функциях format() и print(). В отличии от __repr__(), в ней, при реализации,  мы стараемся создать наиболее информативное представление объекта.

__bytes__()

Метод возвращает объект типа bytes – представление текущего объекта в виде набора байт.

__bool__()

Возвращает True или False.

__call__()

Позволяет использовать объект как функцию, т.е. его можно вызвать.

__len__()

Чаще всего реализуется в коллекциях и сходными с ними по логике работы типами, которые позволяют хранить наборы данных. Для списка (list__len__() возвращает количество элементов в списке, для строки – количество символов в строке. Вызывается функцией len(), встроенной в язык Python.

Функции сравнения

Функция

Операция

Функция

Операция

Функция

Операция

__lt__()

< 

__le__()

<=

__eq__()

==

__ne__()

!=

__gt__()

> 

__ge__()

>=

Эти функции используются, если объекты можно сравнивать между собой, как числа. Синтаксис работы с ними выглядит следующим образом: x.__lt__(y), что соответствует записи x < y.

Функции, эмулирующие числовые типы

Арифметические операции

Функция

Операция

Описание / пример

__add__()

+

Сложение

__sub__()

Вычитание

__mul__()

*

Умножение

__truediv__()

/

Деление

__floordiv__()

//

Целая часть от деления

__mod__()

%

Остаток от деления

__pow__()

**

Возведение в степень

Помимо указанных в таблице, в объектной модели Python, есть методы, позволяющие выполнять инверсные арифметические операции (случай, когда объекты, над которыми производится действие меняются местами), имена таких методов совпадают с перечисленными выше с добавлением символа r перед именем (примеры: __radd__()__rsub__()). Методы для арифметических операции присваивания, таких как *=, += и т.п., имеют имена сходные с табличными с добавлением символа i перед именем (примеры: __iadd__(), __isub__()).

Унарные операции

Функция

Операция

Описание / пример

__neg__()

Отрицательное значение

__pos__()

+

Положительное значение

__abs__()

abs()

Модуль числа

Битовые операции

Функция

Операция

Описание / пример

__lshift__()

<< 

Поразрядный сдвиг влево

__rshift__()

>> 

Поразрядный сдвиг вправо

__and__()

&

Логическое И

__or__()

|

Логическое ИЛИ

__xor__()

^

Исключающее ИЛИ

__invert__()

~

Инверсия

Для битовых операций, также как для арифметических, предполагается возможность реализовывать инверсные операции и битовые операции присваивания.

Примеры

Для иллюстрации использования возможностей объектной модели Python приведем канонический пример с классом, в рамках которого реализуется поддержка операций над векторами.

class Vector():

def __init__(self, x, y):

self.x = x

self.y = y

def __add__(self, v):

return Vector(self.x + v.x, self.y + v.y)

def __sub__(self, v):

return Vector(self.x - v.x, self.y - v.y)

def __repr__(self):

return "Vector({}, {})".format(self.x, self.y)

def __str__(self):

return "({}, {})".format(self.x, self.y)

def __abs__(self):

return (self.x**2 + self.y**2)**0.5

if __name__ == "__main__":

v1 = Vector(3, 4)

print("vector v1 = {}".format(v1))

v2 = Vector(5, 7)

print("vector v2 = {}".format(v2))

print("v1 + v2 = {}".format(v1 + v2))

print("v2 - v1 = {}".format(v2 - v1))

print("|v1| = {}".format(abs(v1)))

Запустив эту программу, вы увидите следующее:

>python object_model.py

vector v1 = (3, 4)

vector v2 = (5, 7)

v1 + v2 = (8, 11)

v2 - v1 = (2, 3)

|v1| = 5.0

Операции сложения и вычитании векторов реализованы в методах __add__() и __sub__(). Модуль вектора – в __abs__(). Функция print(), если ей передать объект типа Vector, в первую очередь вызовет метод __str__(), если этого метода не будет, то вызовется __repr__().

Для эксперимента можете удалить метод  __str__() и получите следующий результат:

>python object_model.py

vector v1 = Vector(3, 4)

vector v2 = Vector(5, 7)

v1 + v2 = Vector(8, 11)

v2 - v1 = Vector(2, 3)

|v1| = 5.0

Вот ещё один пример, который демонстрирует работу с операторами сравнения:

class UserLevel():

us_dict = {"Admin":4, "Operator":3, "Dispatcher":2, "Guest":1}

def __init__(self, user_level):

if user_level in self.us_dict:

self.u_level = user_level

else:

print("Wrong user type!")

self.u_level = "Guest"

def diff(self, level1, level2):

return self.us_dict[level1] - self.us_dict[level2]

def __lt__(self, user):

return True if self.diff(self.u_level, user.u_level) < 0 else False

def __le__(self, user):

return True if self.diff(self.u_level, user.u_level) <= 0 else False

def __eq__(self, user):

return True if self.diff(self.u_level, user.u_level) == 0 else False

def __ge__(self, user):

return True if self.diff(self.u_level, user.u_level) >= 0 else False

def __gt__(self, user):

return True if self.diff(self.u_level, user.u_level) > 0 else False

def __repr__(self):

return "UserLevel({})".format(self.u_level)

def __str__(self):

return self.u_level

if __name__ == "__main__":

need_level = UserLevel("Operator")

print("need level: {}".format(need_level))

user_level = UserLevel("Dispatcher")

print("user: {}".format(user_level))

if user_level >= need_level:

print("Access enabled!")

else:

print("Access denied!")

В этом примере реализован класс UserLevel, который используется для хранения уровня доступа. Объекты этого типа можно сравнивать между собой, используя классические операции сравнения, поддержка этого функционала реализуется через методы, перечисленные в блоке Битовые операции раздела Специальные методы этой статьи.

Что еще почитать на эту тему?

На эту тему интересно написано у Лучано Рамальо в книге “Python. К вершинам мастерства”. Дополнительно рекомендуется обратить внимание на “Python in a Nutshell” Алекса Мартелли и “Python Essential Reference” Девида Бизли.

Популярные репетиторы:

Рейтинг 5 из 5: 45 отзывов
 
C самого начала своего продвижения по службе, я мечтал собрать в одно целое 2 моих основных увлечений: Математику, Информатику и Обучение, когда еще учился в аспирантуре.

Профессиональный математик для школьников и студентов, кандидат физико математических наук, докторант, педагогический стаж более 19 лет, без промедления   подготовит учащихся к экзамену ЕГЭ по математике в 11 класс с помощью новых методик по развитию памяти и   мышления. Помогает в написании работ:курсовых.

Консультации по математическим пакетам MathCad, Microsoft Mathematics и Maxima . Некоторое время потрудился в стартапе по Нейронным сетям и TensorFlow. Участвует в ведущих академических симпозиумах WWW, ICCV и CVPR . Без усилий "кодит" на Perl, Rast и Python.

Занятия ведутся по Google Hangout и локально в Москве м. Китай-город. Более 320 учащихся  поступили «на бюджет» в ВУЗы Москвы: МГТУ, МАИ, МГУ и МЭИ и т.д.. Опыт репетитора по математике для студентов более 20 лет. Hij spreekt Nederlands.

Запись на занятия

Ваше сообщение отправлено