Python Academy
49.6K subscribers
1.08K photos
2 videos
373 links
Python Academy — один канал вместо тысячи учебников

Чат канала: @python_academy_chat

Сотрудничество: @zubar89

Канал включён в перечень РКН: https://rkn.link/TVu
加入频道
ООП: композиция

Композиция — это отношение, при котором объекты одного класса связаны с объектами другого. Такой способ организации взаимодействия между классами также называется ассоциацией.

Как правило, в этом случае объект одного из классов (в примере выше это Salary) является полем другого (Employee). Сложного здесь, как вы видите, ничего нет.

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

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

#классы #ооп
Считаем ссылки на объект

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

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

Если на объект ссылается другой объект, то он имеет ненулевое значение ссылок и не может быть собран как мусор (если, конечно, вы не удалите вручную).

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

#ctypes
Пакетный менеджер pip

Для работы с пакетами в Python есть специальная утилита pip — устанавливается она сразу вместе с интерпретатором.

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

Команды list и freeze покажут все пакеты в текущем окружении, а также их версии. Обратите внимание на то, как выглядит вывод каждой из них.

А с помощью show можно посмотреть информацию о конкретном пакете: название, версию, описание, автора, лицензию и другое.

#pip
Генераторные выражения и списковые включения

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

Если вывести переменные, то видим, что значением переменной l является список, а переменная g хранит в себе объект генератора. И здесь возникает вопрос, что же использовать.

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

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

#генераторы
Работаем с атрибутами объектов

Помимо привычного обращения к атрибутам объектов через точку, в Python есть 4 специальных функции: getattr, setattr, delattr и hasattr.

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

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

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

#классы #атрибуты
Итерируемый счетчик

Еще один классный итератор из itertools — это count, который генерирует бесконечную последовательность чисел.

В аргументах можно задать значения start и step: первый отвечает за начальное значение, а второе за шаг, как и в range.

Обычно count редко используют с циклом for. Чаще можно встретить случаи с функциями типа zip или map.

#itertools
Магические методы

Магические методы — это специальные методы, которые начинаются и заканчиваются двойным подчеркиванием.

Такие методы вызываются не напрямую, а при определенном действии. Например, когда вы складываете два числа с помощью оператора +, вызывается метод __add__().

Встроенные классы имеют много реализованных магических методов по умолчанию. Для примера можете взглянуть на их количество у того же int на картинке выше.

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

Инкремент с помощью __pos__
Как работают арифметические операции
Разница между __str__ и __repr__

Кстати, в английском магический метод еще часто называют dunder, сокращение от double underscore.

#magic
Использование комплексных чисел в Python

Никого здесь уже не удивить такими встроенными типами, как например int, float, и подобными. Но кроме них в Python существует еще один довольно интересный тип, а именно, complex.

В Python комплексные числа представлены в виде x + iy. А точнее говоря, вместо буквы i здесь используется буква j, во избежание некоторой путаницы, поскольку i чаще всего занята под циклы. Python преобразует реальные числа x и y (будь то int или float) в комплексное с помощью функции complex(x,y).

Комплексное число легко можно превратить в строку с помощью функции str или посчитать его модуль с помощью функции abs, а также для доступа к его реальной или мнимой частям можно воспользоваться методами real и imag.

Хотя complex и является встроенным типом, для более удобной работы с комплексными операциями рекомендуется импортировать модуль cmath.

#complex
Decimal и Fraction

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

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

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

#decimal
Дзен и его противоречие

Еще в далеком PEP 20 был предложен Дзен Python — правила, которым рекомендуется следовать при разработке на этом языке. Посмотреть их можно, импортировав встроенный модуль this.

Но здесь забавно то, как этот модуль реализован: оригинальный текст зашифрован с помощью алгоритма ROT13 и декодируется на лету.

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

#zen
Вычисление размера объектов

Для вычисления размера объекта мы можем использовать функцию getsizeof(object[, default]) из модуля sys. Так как в python все по сути является объектами, то и вычислить размер в памяти мы можем у любого такого объекта.

И хотя все built-in (встроенные) объекты и вернут правильный размер, в общем случае это не должно быть верно для каких-либо пользовательских объектов.

Аргумент default позволяет определить значение, которое будет возвращено, если тип объекта не предоставляет средства для извлечения размера и вызовет TypeError .

Функция getsizeof вызывает метод __sizeof__ объекта и добавляет дополнительные служебные данные сборщика мусора.

#getsizeof
Динамическая замена class

Многие знают, что с помощью type можно получить тип объекта. Но не все так просто, по сути type служит динамической заменой инструкции class и позволяет создавать новые объекты типа во время исполнения.

Первый принимаемый аргумент является именем класса и становится атрибутом __name__; второй аргумент является кортежем с перечисленными базовыми типами и становится атрибутом __base__; словарь будет являться телом класса и станет атрибутом __dict__.

#type #class
Полноценный гайд для новичков

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

— Плюсы и минусы Python;
— Зарплаты Python разработчиков;
— Роадмап по скиллам;
— Ресурсы для обучения; 
— Как правильно решать задачи;
— Какой компьютер нужен для программирования.

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

#начинающим
Параметры *args и **kwargs

Все хоть раз видели такую запись, и сейчас мы узнаем, что это за символы. Сообщу сразу, что args и kwargs – общепринятые имена переменных, а разбирать мы будем звездочки перед ними.

В примере функция принимает обязательный аргумент value, а остальных аргументов она как бы не ожидает. В таком случае *args упаковывает все не именованные аргументы в кортеж, а **kwargs – все именованные в словарь.

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

#функции
Что такое lambda-функции

Анонимные функции — крайне полезный аспект языка, которым либо пренебрегают, либо чрезмерно пользуются. Начинающим они могут показаться сложными, но это совсем не так.

Структура очень простая — lambda <arguments>: <expression> . Сначала пишете ключевое слово lambda, далее аргументы через запятую, двоеточие и какое-то выражение, результат которого автоматически вернется.

Такие функции чаще всего используются, когда они больше нигде не понадобятся, то есть определять полноценную функцию нет смысла. Типичные примеры использования — map и filter.

#функции #lambda
Словари вместо switch-case

В Python до сих пор нет switch-case конструкций, но иногда встречается одно хитрое решение — использовать словарь, где значениями будут функции.

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

В этом примере я использовал lambda-функции для упрощения кода, про них можете почитать в предыдущем посте.

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

#словари #функции
Отлавливаем баги с assert

При выполнении инструкции assert с логическим выражением, результат которого равен True, ничего не произойдет.

Но если попробовать выполнить инструкцию assert с логическим выражением, которое равно False, то будет сгенерировано исключение AssertionError.
 
Исключения AssertionError предназначены скорее для отладки. При написании программ на этапе разработки мы можем видеть, что делаем что-то не так (например, передали в метод некорректное значение). 

Также не нужно, к примеру, обрабатывать пользовательский ввод и пытаться обработать исключение AssertionError блоком try-except.

Если в вашем коде будет очень много assert'ов, то это затронет и производительность программы.

#исключения #assert
Сортировка списков по ключу

У списков есть метод sort(), который сортирует элементы. Также есть аргумент reverse, с помощью которого можно отсортировать в обратном порядке при значении True.

Но еще есть аргумент key, отвечающий за критерий сортировки. Он принимает функцию, которая применяется к каждому элементу. Возвращаемый результат и есть критерий, по которому произойдет сортировка.

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

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

#списки
Слоты в классах

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

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

#class #slots
Сохранение документации функции при декорировании

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

Для решения этой проблемы можно воспользоваться декоратором functools.wraps, применяя его к обертке нашего декоратора. В результате имя и сигнатура функции, передаваемой в декоратор, будут копироваться в обертку.

#декораторы #wraps
3 трюка с itertools

Начнем с функции combinations: она позволяет составлять комбинации элементов из итерируемых объектов без повторений. Первый аргумент это сам объект, а второй — длина комбинации.

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

Ну и в заключение, рассмотрим функцию compress, применяющую "маску" из второго аргумента функции к первому. То есть, если в маске на этом месте стоит единица, то в исходном массиве элемент остается нетронутым, и наоборот.

#itertools