Введение
В данной статье рассматриваются встроенные типы данных в Python версии 3.7.3 (создание собственных типов данных можно посмотреть в документации [9]), их краткое описание, разделение на изменяемые и неизменяемые, а также объяснение самого понятия изменяемый или неизменяемый тип данных. Эта статья является логическим продолжением публикации: " Какие вопросы могут задать на собеседовании по Python?. Часть 1".
Что понимают под изменяемыми и неизменяемыми типами данных?
Давайте сразу разберемся с вопросом об изменяемости типов данных.
Изменяемые типы
Под изменяемыми понимают типы, объекты которых могут быть изменены на месте, как, например, список, который имеет модифицирующие его методы list.remove, list.append, ... [10]
Одно из последствий такого поведения является то, что объекты изменяемых типов не могут быть использованы в качестве ключей для словаря. [10]
Неизменяемые типы
Напротив, у неизменяемых объектов отсутствует модифицирующие их методы. [10] Например, в следующем примере будет создан новый объект:
x = 1
x += 1 # x - теперь ссылается на новый объект, 2.
Типы данных
В Python 3 объекты могут иметь следующие типы данных:
1. bool
bool - это логический тип данных, который может содержать значения True или False. bool является подтипом целочисленного типа и, соответственно, почти во всех контекстах ведет себя как 0 для False и 1 для True. Исключением является его преобразование в строковый тип, при котором возвращаются строковые значения 'False' или 'True'. [1-3]
2. None
Этот тип имеет одно значение. Существует только один объект с этим значением, доступ к которому осуществляется через встроенное имя None. Этот тип используется для обозначения отсутствия значения во многих ситуациях, например, он возвращается из функций, которые ничего явно не возвращают. Его истинное значение ложно. [1, 3, 4]
3. Числа
Числа являются неизменяемыми типами данных. К ним относятся встроенные типы int, float, complex, а также типы Decimal и Fractions, которые могут быть импортированы, соответственно, из модулей decimal и fractions [11]
3.1 int
Тип int представляет целые числа, размер которых ограничен лишь объемом оперативной памяти. [1, 2]
3.2 float
Тип float представляет числа с плавающей запятой. Python не поддерживает числа с плавающей запятой одинарной точности: экономия на использовании процессора и памяти, которая обычно является причиной их использования, сводится на нет из-за накладных расходов на использование объектов в Python, поэтому нет смысла усложнять язык двумя типами чисел с плавающей запятой. [1, 2]
Информацию о точности и внутреннем представлении чисел с плавающей запятой для машины, на которой работает ваша программа, доступна в sys.float_info. [4]
3.3 complex
Тип complex представляет собой комплексные числа в виде пары чисел с плавающей запятой двойной точности, которые, в свою очередь, представляют действительную и мнимую части. Действительная и мнимая части комплексного числа z могут быть получены с помощью атрибутов только для чтения z.real и z.imag. [1, 4]
4. Последовательности
4.1 str
Строки являются неизменяемыми последовательностями кодовых точек Unicode. Все кодовые точки в диапазоне U+0000 - U+10FFFF могут быть представлены в виде строки [1, 4].
str является рекурсивной структурой данных, каждая кодовая точка в строке сама является объектом str длиной, равной 1. Вероятно, поэтому у Python отсутствует тип char. [1, 3]
4.2 bytes
Тип bytes представляет собой неизменяемую последовательность одиночных байтов (целых чисел в диапазоне 0 <= x < 256) или, другими словами, неизменяемый массив байтов. Объекты bytes могут быть декодированы в строку с помощью метода decode(). [1, 3, 4]
Поскольку тип bytes является последовательностью целых чисел (подобно кортежу), то для байтового объекта bs, результатом обращения по индексу bs [0] будет целое число, а результатом среза bs [0:1] - будет байтовый объект длины 1. (Это отличается от строки, где и индексирование, и срез будет строкой единичной длины). [4]
4.3 bytearray
Объект bytearray является изменяемым массивом байтов. Помимо того, что байтовые массивы могут быть изменяемыми (и, следовательно, не подлежащими изменению), они обеспечивают тот же интерфейс и функциональность, что и неизменные байтовые объекты bytes. [1 -3]
4.4 list
Список представляет собой последовательность, элементами которой могут быть произвольные объекты Python. [1, 4] Списки реализованы как динамические массивы, что допускает добавление и удаление элементов, а также автоматическую корректировку резервного хранилища, в котором эти элементы содержаться. [3]
4.5 tuple
Кортежи - это неизменяемые последовательности. Аналогично спискам, элементы кортежа могут содержать произвольные объекты Python. [1, 4]
4.6 range
Тип range представляет собой неизменяемую последовательность чисел, обычно используемая в цикле for. [4]
Отображения
5.1 dict
Тип dict или словарь - это изменяемая структура данных, которая является отображением ссылок на объекты, доступ к которым может быть получен по ключу, а не по позиции. Словари реализованы в виде динамически расширяемых хеш-таблиц. [11]
6. Множества
Множества представляют собой неупорядоченные коллекции уникальных неизменяемых хеш-объектов. Множества не могут быть проиндексированы, но являются итерируемыми. [1, 4]
Обычно они используются для удаления дубликатов из последовательности или проверки на принадлежность.
6.1 set
Данный тип представляет изменяемое множество.
6.2 frozenset
frozenset является неизменяемым множеством. Поскольку объект этого типа является неизменяемым, то он может быть использован в другом множестве или в качестве ключа словаря.
7. Ellipsis
Этот тип имеет одно значение. Существует только один объект с этим значением, доступ к которому осуществляется через литерал ... или встроенное имя Ellipsis. Его истинное значение равно True [1, 2, 4, 5]. До PEP 409, Ellipsis использовался исключительно в расширенном синтаксисе получения среза [6].
В Python 3, Ellipsis или ... можно использовать для обозначения атомарных выражений. Такое обозначение может быть альтернативой оператору pass или объекту None в некоторых видах контекста. [11]
8. function
Объекты функций создаются с помощью определений функций. Единственная операция над объектом-функцией - вызывать его:
func (arguments). [4]
Функции являются хэшируемыми и мы вполне можем использовать их как ключи в словаре:
На самом деле существует два вида объектов функций: встроенные и пользовательские. Оба вида поддерживают одну и ту же операцию вызова функции, но их реализация отличается, следовательно - это разные типы объектов. [4]
9. NotImplemented
Этот тип имеет одно значение. Существует только один объект с этим значением, доступ к которому осуществляется через встроенное имя NotImplemented. Числовые методы и методы расширенного сравнения должны возвращать это значение, если они не реализуют операцию для предоставленных операндов. (Затем интерпретатор попытается выполнить отраженную операцию или какой-либо другой запасной вариант, в зависимости от оператора.) Его истинное значение равно True [1, 4].
Заключение
На самом деле, некоторые встроенные типы я не стал здесь рассматривать, например, module, memoryview, code objects и др. Как вы могли заменить встроенных типов не так уж и мало. Вы можете ознакомиться с ними более подробно в официальной документации.
И, напоследок, я решил сделать небольшое резюме этой статьи в виде таблички.
Источники
1. Python documentation, The standard type hierarchy
2. Н.А. Прохоренок, В.А. Дронов, "Python 3. Самое необходимое"
3. Дэн Бейдер "Чистый Python. Тонкости программирования для профи"
4. Python documentation, Built-in Types
5. PEP 409
6. PEP 415
7. sys.float_info
8. Какие вопросы могут задать на собеседовании по Python?. Часть 1
9. Создание собственных типов данных
10. Кеннет Рейтц, Таня Шлюссер, "Автостопом по Python"
11. Марк Лутц. "Python. Карманный справочник"