logo
Ещё

Типы данных в Python

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

Как Python управляет данными?

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

Если вы переходите из языка со статичной типизацией или просто любознательны, то у вас может возникнуть вопрос: «А как динамическая типизация работает внутри Python?». Со статичной типизацией все понятно: каждый тип имеет заранее определенный размер в байтах, и компилятор/интерпретатор выделяет нужное количество места под переменную в стэке, а если место заканчивается – место выделяется уже в куче (что снижает скорость работы, к сожалению). В Python же ничего не понятно: тип данных может меняться во время исполнения (в рантайме), плюс в список можно поместить разные типы данных.

Все дело как раз в том, что любая переменная является объектом, что существенно упрощает работу со ссылками: на любую переменную, даже на число, мы всегда имеем эту самую ссылку. Поскольку на все есть ссылка – интерпретатору не нужно думать, как расширить память в стэке, если в рантайме разработчик присваивает сложный объект переменной, в которой раньше хранилось число – интерпретатор просто создает новый объект в памяти и меняет ссылку переменной, а число, если на него больше никто не ссылается, затем подберет сборщик мусора – так это работает с объектами и в других ЯП, Java как пример. Что касается списков в которые можно помещать любые типы – в списках на самом деле хранятся ссылки, а не сами переменные, поэтому положить в список можно что угодно.

Проблема такого подхода – в скорости работы, потому что любую mutable (изменяемую) переменную Python помещает в кучу – специальную произвольную область памяти. В стэк (быструю область памяти) попадают только immutable (неизменяемые) объекты, которых обычно в приложении не так уж и много. Да, Python имеет некоторые оптимизации, которые его ускоряют – вместо двух переменных с числовым значением «5», например, Python может создать 1 область памяти, в которой хранится «5», и 2 ссылки на нее; но полностью это проблему не решает, динамическая типизация – причина медленной скорости работы Python.

Основные типы данных в Python

Полную информацию обо всех типах данных в Python вы можете почитать в соответствующем разделе официальной документации. Читать там – очень много (экранов 200-300), и большинство типов данных вам вообще никогда в жизни не пригодится, поэтому для начала можете ограничиться теми, которые мы опишем в этом разделе – в 99.9% случаев вы будете пользоваться только ими в своей работе.

Числовой тип

Самый простой тип – в переменных этого типа могут храниться числа. Numbers подразделяются на integral, real и complex; integral, в свою очередь, содержит integers и booleans:

  • Integers. Любые целые числа.
  • Booleans. Булево значение, «True» или «False». По факту булево значение – это 1 или 0, и почти во всех контекстах boolean ведет себя как число.
  • Real. Любые дробные числа. В Python нет дробных чисел с одинарной точностью, только числа с двойной точностью.
  • Complex. Комплексные числа – те, которые имеют реальную и мнимую часть.

Изменяемые последовательности

Последовательность – это некоторый набор значений, проиндексированный неотрицательными числами. Отличительная черта любой последовательности – доступ к элементу последовательности seq с индексом i можно получить по обращению к seq[i]. Последовательности бывают изменяемыми и неизменяемыми – как понятно из названия, первые можно изменять после создание, вторые – нельзя. Изменяемые последовательности в Python – это:

  • Списки. Вероятно, самая используемая последовательность в Python. Списки могут хранить в себе неограниченное количество произвольных элементов, то есть элементов разных типов.
  • Bytearray. Массив байтов. Имеет зеркальное отражение «в лагере» неизменяемых последовательностей – неизменяемый массив байтов.

Если этих изменяемых последовательностей вам не хватает – можете подключить встроенные библиотеки с массивами и коллекциями.

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

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

  • Строки. Хранят в себе наборы символов в Unicode. Самая используемая неизменяемая последовательность.
  • Кортежи. Могут хранить в себе произвольное количество произвольных элементов – то есть работают практически так же, как списки, только без возможности изменения того, что внутри.
  • Bytes. Неизменяемый массив байтов.

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

Множества

Множество (set) – отдельный тип данных. Во множество можно поместить любое количество уникальных неизменяемых объектов. Если попытаться добавить во множество объект, который там уже есть – ничего не произойдет. У множества, в отличие от последовательностей, нет индексации – если вы последовательно добавите во множество числа «1», «2», «3», «4» и «5», после чего выведете множество в консоль, вы можете получить результат вида «5, 2, 3, 1, 4» – или любую другую комбинацию. При этом по множеству можно проходить с помощью for. Множества бывают изменяемыми (set) и неизменяемыми (frozenset).

Словари

Те же списки, но вы сами задаете индексы, и не обязательно использовать числа – в качестве индекса можно задать любой неизменяемый объект, часто для этого используются строки. Словари хранят данные в виде пар «ключ:значение», ключ – это индекс. С версии языка 3.7 словари – упорядоченные, до этого они были неупорядоченными.

Специализированные типы данных в Python

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

  • None. Указывает на отсутствие чего-либо.
  • Ellipsis. Никто толком не знает, зачем он нужен, но известно, что этот объект всегда True, если использовать его в выражениях.
  • Файловые объекты. Позволяют получить доступ к файлу и что-то с ним делать.
  • Функции. Функции в Python – тоже объекты, что позволяет реализовывать базовое функциональное программирование.

Методы для работы с данными

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

  • Сложение/конкатенация. «Объект типа + объект типа». Для чисел результат – сложение, для строк – объединение и так далее.
  • len(). Позволяет получить длину любой последовательности.
  • type(). Позволяет получить название типа данных. Если вам нужно узнать название типа – используйте type(), если вам нужно понять, относятся ли две переменные к одному типу – лучше использовать isinstance().
  • Изменение типа данных. В программировании это называется casting. Для того, чтобы перевести один тип данных в другой (если это возможно), в Python нужно использовать запись «int(переменная)», «str(переменная)» и так далее – если переменная value хранит число 15, то str(value) вернет строку «”15”».

FAQ

Почему не стоит использовать изменяемые объекты в качестве параметров по умолчанию?

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

Как узнать тип переменной?

Воспользуйтесь встроенной функцией type().

Как работает приведение типов?

Поскольку Python – язык со строгой типизацией, вам нужно напрямую изменить тип переменной (casting).

Вывод

Тезисно:

  • Всё в Python является объектом.
  • Основные типы данных – численные, последовательности (изменяемые и неизменяемые), множества и словари.
  • Функция – тоже тип данных, функцию можно, например, передать в качестве аргумента другой функции.
  • Изменить тип переменной в Python можно только явно.