Три редко используемых возможности Python 3, о которых каждый должен знать

Автор оригинала: Brett Fazio
  • Перевод

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

Данная статья является переводом 3 Neglected Features in Python 3 That Everyone Should Be Using.

Перечисления


Перечисления я много использовал в Java и Swift. Продолжаю их использовать теперь и в Python.

Объявление перечисления в Python очень просто сделать и это было возможно и до третьей версии (хотя и с ограничениями):

from enum import Enum

class State(Enum):
  AIR = 0
  LAND = 1
  SEA = 2
  
myState = State.AIR

# Выводит 0
print(myState.value)
# Выводит AIR
print(myState.name)

В коде выше перечисление вводится путем объявления класса, наследованного от Enum. А далее просто описываются все нужные состояния. В моем случае: AIR, LAND и SEA.

Функциональность, которая была добавлена в Python 3 — возможность использовать .value и .name. Они позволяют получить число и строку соответствующие перечислению.

Например, вывод значения State.LAND.name будет LAND.

Перечисления полезны в коде, когда вы хотите иметь некоторые текстовые идентификаторы для констант. Например, вместо сравнения состояния с 0 или 1 гораздо показательнее сравнивать с State.MOVING или State.STATIONARY. Константы могут меняться и если кто-то посмотрит код позже, то слово MOVING даст гораздо больше понимания, чем 0. В результате сильно повышается читабельность кода.

Больше информации можно найти в официальной документации Python 3 по Enum.

Форматирование


Добавленные в версии 3.6, fstrings — это мощное средство форматирования текста. Они позволяют создавать гораздо более читабельный и безошибочный код (чем я наслаждаюсь после перехода из Java). Это лучше, чем format, который использовался ранее в Python. Вот пример использования format:

name = 'Михаил'
blog_title = 'codeatcpp.com'

# Привет, меня зовут Михаил и я пишу в своем блоге codeatcpp.com.
a = "Привет, меня зовут {} и я пишу в своем блоге {}.".format(name, blog_title)

Легко заметить пустые фигурные скобки внутри строки и после список с названиями переменных в определенном порядке.

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

name = 'Михаил'
blog_title = 'codeatcpp.com'

# Привет, меня зовут Михаил и я пишу в своем блоге codeatcpp.com.
a = f"Привет, меня зовут {name} и я пишу в своем блоге {blog_title}."

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

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

Классы данных


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

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

Представьте, что у вас есть программа, в которой вам нужно передавать строку и массив чисел между разными классами. У вас могут быть методы вроде pass(str, arr), но гораздо удобнее сделать класс, который содержит строку и массив в качестве единственных членов класса.

Использование класса данных лучше показывает что вы пытаетесь сделать и также упрощает создание юнит-тестов.

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

from dataclasses import dataclass

# Определяем класс данных
@dataclass
class Vector3D:
    x: int
    y: int
    z: int
      
# Создаем вектор
u = Vector3D(1,1,-1)

# Выводит: Vector3D(x=1, y=1, z=-1)
print(u)

Здесь легко заметить, что определение класса данных очень похоже на определение обычного класса, за исключением того, что используется декоратор @dataclass и затем каждое поле определяется в виде имя: тип.

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

Больше информации про декоратор @dataclass можно найти в официальной документации Python 3.

Заключение


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

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 14

    +2
    Три редко используемых возможности Python 3...

    Вроде как классы и форматирование особенно изучаются в первые часы знакомства с Python.

    Интересно было бы посмотреть на этого «сферического разработчика в вакууме» который не знаком с форматированием и классами. Какой же это «разработчик»? Ага, я не знаю как включить двигатели у самолета, но я уже «пилот», так что ли?
      +5
      не уверен что @dataclass изучается в первые часы
        +3

        Не просто классы, а dataclasses.
        Не просто форматирование, но f-strings, которые всего как пару версий назад завезли.


        Но соглашусь, что новой информации в статье нет, так как уже были статьи с раскрытием этих "фишек" питона.


        По запросу "dataclasses" нашлось 22 публикации, включая эту.

          0
          Мне кажется, для такого простого и удобного инструмента как f-строки пара версий достаточный строк, чтобы о нем уже знало большинство разработчиков.
          0
          Ну так речь про форматирование через новый механизм fstrings, а не всем привычный format, практически уверен что в большинстве учебных заведений о нем не рассказывают(если вообще сами знают). Дата-классы тем более не изучаются в базовом курсе по языку.
          0

          Насчёт fstrings стоит также добавить, что этот способ поддерживает опции форматирования как метод format, а также работает быстрее этого метода и форматирования процентом (пример сравнения здесь).

            +3

            И рядом с dataclass я бы ещё упомянул про namedtuple – функционал далеко не новый, но идейно схожий, тоже предоставляет лаконичный способ создания классов данных без написания однотипного кода конструктора и repr'a, и тоже используемый реже, чем стоило бы. Основное отличие от dataclass – данные в namedtuple неизменны после создания, зато имеется некоторый буст по скорости работы (т.к под капотом минималистичный кортеж, а не список/словарь) и используемой памяти (т.к имена полей не дублируются в кортежах, а хранятся только в классе). Есть ли что-то такое у dataclasses? Предполагаю, что может быть такая же оптимизация по памяти на основе единого места хранения имён полей.


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

              0
              Есть примеры с замерами про «с namedtuple имеется некоторый буст по скорости работы»?
              например вот тут по тестам особой разницы нет, а памяти требует больше, насколько я понимаю.
              +2
              Добавил бы про форматирование что там можно выполнять код прямо внутри скобок

              >>> print(f'len = {len("abc")}')
              len = 3
              
                0
                Но лучше так не делать. Вынести логику в строку до, внутри f-строки оставить только форматирование.
                  0
                  почему?
                  Если у меня там какой-то код который не трогает бизнес логику, зачем создавать лишние переменные?

                  Я например использую внутри вычисление длины списка, или там upper/lower или еще что, не меняющее исходные данные но создающее нужный мне вывод.
                0

                dataclasses Можно использовать только как dto ?

                  0

                  Можно, но неудобно сериализовать в json. Удобнее pydentic, но и в нем свои грабли в стиле превратим питончик в javascript. В итоге в питоне как было 100500 объединять данные в структуры так и осталось.

                  0
                  За Enum спасибо.
                  Насчет dataclasses, для меня наиболее привлекательна упрощенная конструкция, без необходимости в __init__ и __repr__.

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

                  Самое читаемое