python лучшие практики и инструменты pdf

Книга «Python. Лучшие практики и инструменты»

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

Это не значит, что в книге нет ничего интересного для любителей. Она отлично подойдет для тех, кто хочет выйти на новый уровень в изучении Python. Базовых навыков языка будет достаточно, чтобы понять изложенный материал, хотя менее опытным программистам придется приложить некоторые усилия. Книга также будет хорошим введением в Python 3.7 для тех, кто слегка отстал от жизни и пользуется версией Python 2.7 или еще более ранней.

Наибольшую пользу данная книга принесет веб- и бэкенд-разработчикам, поскольку в ней представлены две темы, особенно важные именно для этих специалистов: надежное развертывание кода и параллелизм.

Паттерны доступа к расширенным атрибутам

Изучая Python, многие программисты C++ и Java удивляются отсутствию ключевого слова private. Наиболее близкая к нему концепция — это искажение (декорирование) имени (name mangling). Каждый раз, когда атрибут получает префикс __, он динамически переименовывается интерпретатором:

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

Это сделано специально для того, чтобы избежать конфликта имен по наследованию, так как атрибут переименовывается именем класса в качестве префикса. Это не точный аналог private, поскольку атрибут может быть доступен через составленное имя. Данное свойство можно применить для защиты доступа некоторых атрибутов, однако на практике __ не используется никогда. Если атрибут не является публичным, то принято использовать префикс _. Он не вызывает алгоритм декорирования имени, но документирует атрибут как приватный элемент класса и является преобладающим стилем.

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

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

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

Классы дескрипторов основаны на трех специальных методах, которые формируют протокол дескриптора:

__set__(self, obj, value) — вызывается всякий раз, когда задается атрибут. В следующих примерах мы будем называть его «сеттер»;

__get__(self, obj, owner=None) — вызывается всякий раз, когда считывается атрибут (далее геттер);

__delete__(self, object) — вызывается, когда del вызывается атрибутом.

Дескриптор, который реализует __get__ и __set__, называется дескриптором данных. Если он просто реализует __get__, то называется дескриптором без данных.

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

Для ясности приведем пример из официальной документации Python, в котором показано, как дескрипторы работают в реальном коде:

Вот пример его использования в интерактивном режиме:

Пример ясно показывает, что если класс имеет дескриптор данных для этого атрибута, то вызывается метод __get__(), чтобы вернуть значение каждый раз, когда извлекается атрибут экземпляра, а __set__() вызывается всякий раз, когда такому атрибуту присваивается значение. Использование метода __del__ в предыдущем примере не показано, но должно быть очевидно: он вызывается всякий раз, когда атрибут экземпляра удаляется с помощью оператора del instance.attribute или delattr(instance, ‘attribute’).

Разница между дескрипторами с данными и без имеет большое значение по причинам, которые мы упомянули в начале подраздела. В Python используется протокол дескриптора для связывания функций класса с экземплярами через методы. Они также применяются в декораторах classmethod и staticmethod. Это происходит потому, что функциональные объекты по сути также являются дескрипторами без данных:

Это верно и для функций, созданных с помощью лямбда-выражений:

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

Пример из реальной жизни: ленивое вычисление атрибутов. Один из примеров использования дескрипторов — задержка инициализации атрибута класса в момент доступа к нему из экземпляра. Это может быть полезно, если инициализация таких атрибутов зависит от глобального контекста приложения. Другой случай — когда такая инициализация слишком затратна, и неизвестно, будет ли атрибут вообще использоваться после импорта класса. Такой дескриптор можно реализовать следующим образом:

Ниже представлен пример использования:

Официальная библиотека OpenGL Python на PyPI под названием PyOpenGL использует такую технику, чтобы реализовать объект lazy_property, который является одновременно декоратором и дескриптором данных:

Такая реализация аналогична использованию декоратора property (о нем поговорим позже), но функция, которая оборачивается декоратором, выполняется только один раз, а затем атрибут класса заменяется значением, возвращенным этим свойством функции. Данный метод часто бывает полезен, когда необходимо одновременно выполнить два требования:

В следующем примере показано возможное использование модифицированной версии декоратора lazy_property PyOpenGL (здесь lazy_class_attribute) в некоем абстрактном приложении OpenGL. Изменения оригинального декоратора lazy_property требуются для того, чтобы разрешить совместное использование атрибута различными экземплярами класса:

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

Свойства предоставляют встроенный тип дескриптора, который знает, как связать атрибут с набором методов. Свойство принимает четыре необязательных аргумента: fget, fset, fdel и doc. Последний из них может быть предусмотрен для определения строки документации, связанной с атрибутом, как если бы это был метод. Ниже приведен пример класса Rectangle, которым можно управлять либо путем прямого доступа к атрибутам, хранящим две угловые точки, либо с помощью свойств width и height:

В следующем фрагменте кода приведен пример таких свойств, определенных в интерактивной сессии:

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

Приведенный в следующем примере код не сможет переопределить реализацию метода fget из свойства width родительского класса (Rectangle):

Чтобы решить эту проблему, все свойство следует перезаписать в производном классе:

К сожалению, код имеет кое-какие проблемы с сопровождением. Может возникнуть путаница, если разработчик решит изменить родительский класс, но забудет обновить вызов свойства. Именно поэтому не рекомендуется переопределять только части поведения свойств. Вместо того чтобы полагаться на реализацию родительского класса, рекомендуется переписать все методы свойств в производных классах, если нужно изменить способ их работы. Обычно других вариантов нет, поскольку изменение свойств поведения setter влечет за собой изменение в поведении getter.

Лучшим вариантом создания свойств будет использование property в качестве декоратора. Это позволит сократить количество сигнатур методов внутри класса и сделать код более читабельным и удобным в сопровождении:

Интересная функция, которая очень редко используются разработчиками, — это слоты. Они позволяют установить статический список атрибутов для класса с помощью атрибута __slots__ и пропустить создание словаря __dict__ в каждом экземпляре класса. Они были созданы для экономии места в памяти для классов с малочисленными атрибутами, так как __dict__ создается не в каждом экземпляре.

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

Эту возможность нужно использовать с осторожностью. Когда набор доступных атрибутов ограничен слотами, намного сложнее добавить что-то к объекту динамически. Некоторые известные приемы, например обезьяний патч (monkey patching), не будут работать с экземплярами классов, которые имеют определенные слоты. К счастью, новые атрибуты можно добавить к производным классам, если они не имеют собственных определенных слотов:

Михал Яворски — программист на Python с десятилетним опытом. Занимал разные должности в различных компаниях: от обычного фулстек-разработчика, затем архитектора программного обеспечения и, наконец, до вице-президента по разработке в динамично развивающейся стартап-компании. В настоящее время Михал — старший бэкенд-инженер в Showpad. Имеет большой опыт в разработке высокопроизводительных распределенных сервисов. Кроме того, является активным участником многих проектов Python с открытым исходным кодом.
Тарек Зиаде — Python-разработчик. Живет в сельской местности недалеко от города Дижон во Франции. Работает в Mozilla, в команде, отвечающей за сервисы. Тарек основал французскую группу пользователей Python (называется Afpy) и написал несколько книг о Python на французском и английском языках. В свободное от хакинга и тусовок время занимается любимыми хобби: бегом или игрой на трубе.

Вы можете посетить его личный блог (Fetchez le Python) и подписаться на него в Twitter (tarek_ziade).

О научном редакторе

Коди Джексон — кандидат наук, основатель компании Socius Consulting, работающей в сфере IT и консалтинга по управлению бизнесом в Сан-Антонио, а также соучредитель Top Men Technologies. В настоящее время работает в CACI International ведущим инженером по моделированию ICS/SCADA. В IT-индустрии с 1994 года, еще со времен службы в ВМФ в качестве ядерного химика и радиотехника. До CACI он работал в университете в ECPI в должности ассистента профессора по компьютерным информационным системам. Выучился программированию на Python самостоятельно, написал книги Learning to Program Using Python и Secret Recipes of the Python Ninja.

Для Хаброжителей скидка 25% по купону — Python

По факту оплаты бумажной версии книги на e-mail высылается электронная книга.

Источник

Мой топ книг о Python

Привет, Хабр! Я Слава, руководитель команды «Профессиональные инструменты» в Циане, член ПК Moscow Python Conf и член core-команды авторов в Яндекс.Практикуме.

Вместе с ребятами мы развиваем курс «Мидл python-разработчик», и сегодня я хочу поделиться моим личным списком книг, которые помогут вам структурировать и углубить свои знания о разработке на языке Python.

python лучшие практики и инструменты pdf. Смотреть фото python лучшие практики и инструменты pdf. Смотреть картинку python лучшие практики и инструменты pdf. Картинка про python лучшие практики и инструменты pdf. Фото python лучшие практики и инструменты pdf

«Изучаем Python», Марк Лутц

python лучшие практики и инструменты pdf. Смотреть фото python лучшие практики и инструменты pdf. Смотреть картинку python лучшие практики и инструменты pdf. Картинка про python лучшие практики и инструменты pdf. Фото python лучшие практики и инструменты pdf

Открывает топ книга Марка Лутца «Изучаем Python». Она занимает особое место в моей карьере — моё изучение Python проходило именно по ней. В студенчестве она казалась мне фундаментальным трудом — в книге почти полторы тысячи страниц!

Книга позволит войти в Python, что называется, с нуля. Почему люди программируют на Python? Кто использует Python сегодня? Что можно делать при помощи Python? Каковы сильные стороны Python? Ответы на эти вопросы позволят получить общее представление о языке.

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

Дальше следует описание типов данных и особенностей работы с ними. Отдельными главами раскрывается работа со строками и словарями. Вы узнаете о ветвлении и циклах, итераторах, генераторах, функциях и их аргументах, о модулях и пакетах как способах организации кода. Затем следует введение в ООП: классы, наследование, перегрузка операторов, полиморфизм и метаклассы. Рассказывается об исключениях, о их роли в языке.

На мой взгляд, «Изучаем Python» очень плавно и всеобъемлюще знакомит читателя с миром Python, с одной стороны, не углубляясь в детали, с другой — давая всю полноту картины.

«Высокопроизводительный Python: практическое пособие для людей», Миша Горелик, Ян Освальд

python лучшие практики и инструменты pdf. Смотреть фото python лучшие практики и инструменты pdf. Смотреть картинку python лучшие практики и инструменты pdf. Картинка про python лучшие практики и инструменты pdf. Фото python лучшие практики и инструменты pdf

Второе место топа занимает книга М. Горелика и Я. Освальда «Высокопроизводительный Python: практическое пособие для людей».

Книга позволит вам немного заглянуть под капот языка. Что вообще такое высокая производительность применительно к Python? Книга знакомит с виртуальной машиной Python, учит пользоваться инструментами профилирования для поиска узких мест в использовании процессорного времени, рассказывает о типах данных с точки зрения их внутреннего устройства.

Вы узнаете о многопоточности, асинхронном и мультипроцессорном исполнении, о том, как организовать кластерные вычисления и как потреблять меньше оперативной памяти. Для особо искушённых есть отдельная глава о компиляции кода на Python в C.

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

«Python. Разработка на основе тестирования», Гарри Персиваль

python лучшие практики и инструменты pdf. Смотреть фото python лучшие практики и инструменты pdf. Смотреть картинку python лучшие практики и инструменты pdf. Картинка про python лучшие практики и инструменты pdf. Фото python лучшие практики и инструменты pdf

Следующая книга топа — «Python. Разработка на основе тестирования» Гарри Персиваля. Мне посчастливилось пообщаться с Гарри в рамках прошедшей Russian Python Week 2020. Говорят, британцы чопорные, со странным чувством юмора. Я думаю, что это стереотипы. Гарри много и смешно шутил, улыбался, рассказывал истории из жизни, был очень открыт. Лучше всего о своей книге Гарри расскажет сам.

python лучшие практики и инструменты pdf. Смотреть фото python лучшие практики и инструменты pdf. Смотреть картинку python лучшие практики и инструменты pdf. Картинка про python лучшие практики и инструменты pdf. Фото python лучшие практики и инструменты pdf

Меня иногда спрашивают, как я пришёл к тому, чтобы написать эту книгу. Впервые я изучил Python по книге «Dive Into Python» — это было примерно в 2008-м. Я изучал словари, строки, узнавал различные фичи языка — все вот эти вещи. И где-то к 14-й главе впервые появились слова о юнит-тестировании. Там нужно было написать калькулятор римских чисел. И было написано, что гораздо легче это сделать, если вы пишете юнит-тесты. Я подумал: «О, это звучит круто!» Но это звучало как что-то, что вам следует делать. Как чистить зубы зубной нитью — хорошо бы, чтобы вы это делали каждый день. Разумеется, с таким посылом я проигнорировал этот совет полностью и сразу же о нём забыл. К тому моменту я программировал на Python уже три недели — зачем мне какое-то юнит-тестирование? У меня и так дела идут хорошо! Если я напишу небольшое Django-приложение, несколько веб-страниц — без проблем, я могу всё это проверить. И знаете что? У меня действительно было всё отлично. Поначалу.

Когда моё приложение было небольшим, было очень просто проверить руками, работает оно или нет. Где-то на второй неделе разработки у меня уже было восемь различных модулей, 12 веб-страниц, появилось множественное наследование веб-форм, и перед очередным изменением я стал рассуждать так.

– Я внесу изменения сюда. О, нет, это поломает мне вон тот класс. Лучше изменю здесь. Хотя… есть риск, что перестанет работать веб-форма. Лучше вот сюда. Да, точно, сюда! Ах, черт, всё равно сломалось!

И довольно быстро даже крошечное изменение стало для меня очень болезненным. Я не представлял, что на самом деле от чего зависит, страх вносить изменения сковал меня, я не мог ничего отрефакторить — мой код превратился в лапшу.

Когда я пришёл на свою первую работу, там практиковали разработку через тестирование и экстремальное программирование. И я был уже готов усвоить свой урок, но всё ещё много жаловался: «Юнит-тесты и функциональные тесты? Зачем так много тестов?» Разработка была примерно такой: ты делаешь микроизменение — и запускаешь тест. Делаешь ещё микроизменение — снова запускаешь тест. И так всё время. Я говорил: «Вы серьёзно? Неужели мы не можем пропустить этот шаг, мы сэкономим время!» На что мне спокойно говорили: «Нет-нет, Гарри, продолжай делать так». Я жаловался, я ныл, это было тяжело, это занимало много времени. Но! Через какое-то время мне открылась вся прелесть такого подхода! Я понял, что до этого делал что-то не так, и что вот он — правильный путь. Спустя пару лет я решил написать книгу об этом.

Разработка на основе тестирования — не естественная вещь; чтобы проникнуться, нужна практика. В книге я как раз и пытаюсь дать немного практики.

Книга позволит вам переосмыслить вашу работу и подход к ней, буквально перевернёт сознание. Многие рутинные вещи обретут новый смысл, к ним появится интерес. Качество тестов заметно улучшится, и это неизбежно повлияет на качество кода и архитектуру приложения.

«Architecture Patterns with Python: Enabling Test-Driven Development, Domain-Driven Design, and Event-Driven Microservices», Гарри Персиваль, Боб Грегори

python лучшие практики и инструменты pdf. Смотреть фото python лучшие практики и инструменты pdf. Смотреть картинку python лучшие практики и инструменты pdf. Картинка про python лучшие практики и инструменты pdf. Фото python лучшие практики и инструменты pdf

Я не мог не поговорить с Гарри Персивалем о новой книге, над которой он работает в соавторстве с Бобом Грегори, — «Архитектурные паттерны в Python». Книгу можно почитать бесплатно на сайте www.cosmicpython.com. Гарри продолжает.

В конце первой книги я стал говорить о разных типах тестов. В проекте могут быть низкоуровневые юнит-тесты, интеграционные тесты, где мы проверяем интеграцию с API, или с файловой системой, или с базой данных, а также высокоуровневые тесты — e2e-тесты, функциональные тесты; возможно, тесты на всю систему целиком. Я начал рассуждать о правильном балансе, как много каких тестов должно быть, — об идее пирамиды тестирования. Я также рассуждал о цене, которую нужно за тесты платить: некоторые тесты проходят очень быстро, некоторые медленно, некоторые более надёжные, некоторые менее. Оказалось, что это тяжело — найти правильный баланс скорости тестов и уверенности в том, что они надёжные.

Новая книга пытается дать ответ на этот вопрос. Она о выборе архитектурных шаблонов, о способах структурировать ваш код, которые позволят получить максимальное покрытие юнит-тестами и минимальное количество тяжёлых e2e- и интеграционных тестов. И достигается это как раз хорошим дизайном вашего приложения. Это непросто.

Мне невероятно повезло: я встретил своего коллегу Боба, который оказался экспертом в вопросе. Он стал соавтором книги и рассказал мне о том, как он решает эту задачу. Мы транслировали несколько хороших идей из мира Java и C# (представителей энтерпрайз-мира) в мир Python. Разумеется, мы не просто вставляли код Java в Python (это было бы ужасно), мы пытались ответить на вопрос, как это лучше всего делать в стиле pythonic way.

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

Книгу стоит читать как продолжение «Python. Разработка на основе тестирования». Если вам понравилась первая книга, а идеи, рассказанные там, нашли у вас отклик, то вторая книга ответит на все ваши вопросы и поможет воплотить подход в жизнь — на работе или в вашем личном проекте.

«Python. К вершинам мастерства», Лучано Рамальо

python лучшие практики и инструменты pdf. Смотреть фото python лучшие практики и инструменты pdf. Смотреть картинку python лучшие практики и инструменты pdf. Картинка про python лучшие практики и инструменты pdf. Фото python лучшие практики и инструменты pdf

Замыкает сегодняшний топ книга «Python. К вершинам мастерства» великолепного Лучано Рамальо. Книга стала очень успешной и была переведена на восемь языков.

Если попытаться одной строкой раскрыть, о чём эта книга, то я бы сказал так: она о том, как использовать Python 3 наилучшим возможным способом.

Лучано 66 лет, он живёт и работает в Сан-Паулу в Бразилии. Мне посчастливилось пообщаться с ним в рамках прошедшей Russian Python Week 2020. Несмотря на возраст, Лучано показался мне очень живым, открытым и жизнерадостным собеседником.

python лучшие практики и инструменты pdf. Смотреть фото python лучшие практики и инструменты pdf. Смотреть картинку python лучшие практики и инструменты pdf. Картинка про python лучшие практики и инструменты pdf. Фото python лучшие практики и инструменты pdf

Сейчас Лучано работает над вторым изданием книги. Он поделился, что основным изменением в новой книге будет глава «Введение в Type Hints» — она ещё не закончена, но уже сейчас в ней 60 страниц, и это будет самая большая глава книги!

Однажды Лучано позвали играть в волейбол.

— Я не умею играть в волейбол, — сказал Лучано.
— Да никто понятия не имеет, как играть в волейбол, нам просто нужен ещё один человек, чтобы сформировать команду, — ответили ребята.

В команде только капитан был профессионалом. Он объяснил: игрок с дальней части поля передаёт мяч игроку в центре, он делает передачу игроку под сеткой, который в свою очередь отправляет мяч на сторону противника. Это Best Practice, так играют Pro.

Игра началась, команда действовала по инструкции и со временем начала проигрывать.

Реальность была такова, что никто за исключением капитана не умел играть достаточно хорошо, и часто при передачах команда теряла мяч — он падал на землю, и ход переходил к противнику.

Лучано собрал команду.

— Давайте перестанем притворяться, что мы Pro — на самом деле мы не умеем профессионально играть! Давайте сразу закидывать мяч на сторону противника без передач внутри — так, как мы делали когда-то давно в школе!

И это сработало! Это не было Best Practice, но эта тактика лучше всего подходила к ситуации и для команды, которая у них была. И в конце концов это привело к победе.

Эта небольшая история показательна и для мира Python. Нужно понимать, что Python используют очень много людей, которые не являются профессиональными разработчиками — это физики, биологи, социологи и другие. Нужно, чтобы инструмент не требовал от них выполнения Best Practice, а позволял решать насущную задачу. И Python это позволяет.

Лучано очень любит программировать. Он начал изучать Python 20 лет назад и с тех пор обучил ему многих других людей. Лучано обнаружил, что поскольку Python очень лёгок для обучения, иногда люди даже не читают tutorial полностью. Из-за этого иногда, читая чужой код, можно обнаружить, что человек пишет Java-код на Python или Ruby-код на Python, то есть пытается повторить на другом языке то, к чему он привык. Лучано создал курс «Python для тех, кто знает Python». После этого он много выступал на тему того, как делать те или иные вещи в стиле pythonic way. Так и родилась книга.

Книга стала очень успешной и в мире, и для самого Лучано: он получил работу в ThoughtWorks. Он очень хотел там работать, но не решался отправлять к ним своё резюме из-за высоких требований к кандидатам. После того как книга вышла в свет, они сами к нему пришли. Сегодня ThoughtWorks поддерживают Лучано как публичного спикера точно так же, как поддерживают Мартина Фаулера.

Русское название для книги предложил Python core developer Юрий Селиванов. Лучано считает, что это хороший перевод его книги.

Если вы серьёзно настроены построить карьеру Python-разработчика, то эта книга для вас.

Зачем читать книги

Я глубоко убеждён, что читать книги необходимо людям всех возрастов. Не только литературу профессиональную, но и художественную. Книги действуют на человека, как точильный камень действует на саблю, — они придают знаниям остроту.

Стивен Р. Кови в своей книге «7 навыков высокоэффективных людей» называет это «затачиванием пилы». Этот навык — ваши личные ресурсы и средства. Он поддерживает и развивает самый ценный ваш ресурс — вас самих.

«Как ты узнаёшь новое?» — вопрос, который обычно я задаю кандидатам на собеседованиях. Ответ на него для меня действительно важен, и тут мне недостаточно услышать про чтение статей, просмотр видео на ютубе или прослушивание подкастов. Только книги придают знаниям структуру, без разрывов и со всей полнотой контекста проводя читателя к просветлению.

Перефразируя Антона Птушкина, скажу: «Читайте, оно того стоит!»

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *