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

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

Типизация в языках программирования

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

Сильная и слабая типизация

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

Языки с сильной типизацией (например, Python, Java, C#) требуют явное преобразование типов (ещё называемое их приведением) перед выполнением операций над несовместимыми типами данных. Поэтому попытка сложить число и строку в Python приведет к ошибке TypeError:

12 + "5"
# Ошибка: TypeError: unsupported operand type(s) for +: 'int' and 'str'

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

Языки со слабой типизацией (например, JavaScript, PHP) более лояльны к смешению типов и часто выполняют автоматическое (неявное) преобразование типов, поэтому, например, в JavaScript мы можем сложить число со строкой:

12 + "5"; // В результате получится "125"

Здесь число 12 автоматически преобразуется в строку "12", после чего будет выполнена конкатенация (сложение) строк.

Явная и неявная типизация

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

Языки с явной типизацией (C++, C#, Java) требуют явное указание типа переменной при ее объявлении. Например, в C++ следует указывать тип int для целого числа и std::string для строки:

int age = 26; // Явное указание типа (целое число)
std::string name = "Михаил"; // Явное указание типа (строка)

Языки с неявной типизацией (Python, JavaScript, PHP) позволяют создавать переменные без явного указания их типа. Так интерпретатор Python сам определяет тип переменной на основе присваиваемого значения:

age = 26  # Автоматическое определение типа как целого числа
name = "Михаил"  # Автоматическое определение типа как строки

Неявную типизацию иногда называют «утиной типизацией» – если что-то выглядит как утка, плавает как утка и крякает как утка, то, вероятно, это и есть утка. То есть, тип объекта определяется не его явным объявлением, а его поведением (набором доступных методов и свойств).

Динамическая и статическая типизация

Эта характеристика определяет, когда происходит определение типа переменной.

В языках с динамической типизацией (Python, JavaScript, PHP) тип переменной определяется во время выполнения программы, когда ей присваивается значение. В Python одна и та же переменная может последовательно хранить значения разных типов:

length = 25  # Тип length - целое число
length = "Бесконечная"  # Теперь тип length - строка

В языках со статической типизацией (C/C++, C#, Java) тип переменной должен быть указан при её объявлении и не может быть изменен после:

int length = 25; // Тип length - целое число
length = "Бесконечная"; // Ошибка, так как length может быть только числом

Здесь на языке C++ переменная length объявлена как целое число, поэтому присваивание ей позже строкового значения приведёт к ошибке при компиляции.

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

Встроенные типы данных в Python можно условно разделить на несколько категорий в зависимости от их основного назначения:

  • Числа используются для арифметических операций.
  • Строки служат для работы с текстом.
  • Логический тип позволяет использовать понятия истинности (True) и ложности (False) для оценки выражений.
  • Коллекции, такие как списки, кортежи, множества и словари, используются для хранения наборов данных. Строки тоже можно отнести к коллекциям, так как они хранят наборы символов.
Основные встроенные типы данных в Python

Название

Обозначение

Определение

Пример

Целые числа

int

Натуральные числа, числа противоположные им и ноль

0, -14, 372

Числа с плавающей точкой

float

Вещественные числа в виде десятичной дроби

0.5, 1.2, 23.48

Строки

str

Упорядоченные последовательности символов, заключенные в кавычки

"Привет", "Как дела?"

Логический тип

bool

Представляет истинность или ложность

True, False

Списки

list

Упорядоченные изменяемые последовательности элементов.

[1, "Яблоко", "Груша"]

Кортежи

tuple

Упорядоченные неизменяемые последовательности элементов

("Солнце", "Луна")

Словари

dict

Упорядоченные (с версии Python 3.7) последовательности пар «ключ-значение»

{"Имя": "Александр", "Фамилия": "Невский", "Возраст": 43}

Множества

set

Неупорядоченные коллекции уникальных элементов

{"Красный", "Белый", "Синий"}

Также существует специальный тип данных NoneType, предназначенный для обозначения отсутствия какого-либо значения. Обычно он представлен единственным объектом – None

Использование None распространено в ситуациях, когда требуется явно показать, что переменная ничего не содержит или функция ничего не возвращает.

Аннотации типов

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

Аннотации стали частью стандарта языка начиная с версии Python 3.5 и позволяют указать тип переменной через двоеточие после её имени:

имя_переменной: тип_переменной

Например, мы можем явно указать, что переменная name ожидается строкового типа, а переменная grades – это список:

name: str = "Бурундуков Алексей"
grades: list = [5, 4, 5, 5]

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

Изменяемые и неизменяемые типы данных

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

Image Gallery

Типы данных по изменяемости

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

Например, создадим переменную числового типа:

n = 10
print(id(n)) 
# Вывод: 140717977647832

После этого прибавим к этой же переменной другое число с помощью оператора сложения с присваиванием:

n += 2  # Эквивалентно n = n + 2
print(id(n)) 
# Вывод: 140717977647896

Как видите, идентификатор изменился, так как числа являются неизменяемым типом данных. После изменения значения переменной n в памяти был создан новый объект со значением 12, на который теперь указывает переменная n.

Image Gallery

Изменение значения переменной целочисленного типа

На целое число 10 больше нет ссылок, поэтому он будет удален сборщиком мусора.

Объекты изменяемого типа (списки, множества, словари), наоборот, могут изменять своё содержимое без создания нового объекта и без изменения своего идентификатора в памяти.

Создадим список со школьными предметами:

subjects = ["Математика", "Информатика", "Физика"]
print(id(subjects)) 
# Вывод: 2076557039872

После этого добавим в список новый элемент, сложив его с другим списком:

subjects += ["Русский язык"]  # Эквивалентно subjects = subjects  + ["Русский язык"]
print(id(subjects)) 
# Вывод: 2076557039872

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

Image Gallery

Изменение значения переменной списочного типа

Определение типа переменной

Узнать тип данных переменной позволяет функция type().

Функция

type(object)

Описание

Возвращает тип данных, к которому принадлежит объект object

Параметры

  • object – объект, тип которого требуется определить

Возвращаемое значение

Тип данных объекта

Например, для строки данная функция вернёт <class 'str'>, а для списка – <class 'list'>:

mouse = "Микки Маус" # Строка  
print(type(mouse)) 
# Вывод: <class 'str'>

toys = ["Кукла", "Машинка", "Уточка"] # Список
print(type(toys)) 
# Вывод: <class 'list'>
Робот Кеша читает

Сейчас мы называем целые числа, строки или списки типами данных. Но позже вы узнаете, что на самом деле за каждым типом данных скрывается понятие «класс», поэтому функция type() возвращает именно <class 'название_типа'>. Класс – это шаблон, по которому создаются объекты. Поэтому каждый тип данных соответствует своему классу, и именно классы задают правила поведения для каждого объекта этого типа.

И если функция type() возвращает тип переменной, то функция isinstance() позволяет проверить принадлежность переменной определённому типу. При этом в зависимости от результата проверки данная функция возвращает одно из значений логического типа данных – True (с англ. – истина) или False (с англ. – ложь).

Функция

isinstance(object, type)

Описание

Возвращает True, если объект object принадлежит типу type, иначе – False

Параметры

  • object – объект, который проверяется на принадлежность типу type
  • type – тип, на принадлежность к которому проверяется object

Возвращаемое значение

True или False

Например, если целочисленную переменную проверять на принадлежность к типу int (целые числа), то данная функция вернёт True, а если к типу str (строки) – то False:

x = 10
print(isinstance(x, int)) 
# Вывод: True
print(isinstance(x, str)) 
# Вывод: False

Функция isinstance() особенно полезна, когда нужно проверить, является ли объект экземпляром определенного типа перед выполнением каких-либо специфичных для этого типа операций.

Примеры

Пример 1. Управление данными в системе учета товаров

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

# Название товара (строка)
product_name: str = "Dell Vostro 3520"
# Количество на складе (целое число)
quantity_in_stock: int = 50 
# Доступность товара (логический тип)
is_available: bool = True
# Накопители данных (список)
data_storage: list = ["SSD M.2 PCIe 512 Гб", "Свободный слот 2.5 SATA"]
# Количество USB разъёмов (словарь)
connectors: dict = {"USB 2.0": 1, "USB 3.0": 2}

Пример 2. Заказ в интернет-магазине

Статус оплаты заказа в интернет-магазине может быть как оплачен, то есть соответствовать логическому значению True, так и не оплачен – False. Но по умолчанию он должен соответствовать значению None типа NoneType. В таком случае аннотации типов позволяют указывать несколько допустимых типов с помощью оператора | (логическое «или»):

# Статус оплаты заказа (логическое значение или None)
order_status: bool | None = None 
# Номер заказа, если он уже создан (целое число или None)
order_id: int | None = None
# Стоимость заказа (вещественное число или None)
order_value: float | None = None
# Товары в заказе (список или None)
items: list | None = None
# Желаемая дата доставки (строка или None)
delivery_date: str | None = None

Итоги

  • Тип данных переменной определяет, какие виды значений она может хранить и какие операции над этими значениями можно выполнять
  • Типизация определяет как язык программирования работает с различными типами данных.
  • Сильная типизация (Python) требует преобразование типов для несовместимых операций, а при слабой типизации (JavaScript) типы преобразуются автоматически.
  • Неявная типизация (Python) не требует указание типа при объявлении переменной, а явная типизация (C++), наоборот, требует указывать тип данных переменной.
  • Динамическая типизация (Python) позволяет изменять тип данных переменной во время выполнения кода, а при статической типизации (C++) тип переменной объявляется при компиляции и не меняется.
  • Аннотации типов позволяют явно указывать ожидаемые типы переменных и не влияют на выполнение программы.
  • К основным встроенным типам данным относятся целые числа (int) и числа с плавающей точкой (float), логические значения (bool: True и False), специальный тип NoneType (объект None), а также коллекции: строки (str), кортежи (tuple), списки (list), множества (set) и словари (dict).
  • Неизменяемые типы (числа, строки, кортежи) при изменении создают новый объект с новым идентификатором. Изменяемые типы (списки, множества, словари), наоборот, изменяют своё содержимое без создания нового объекта.
  • Функция type() возвращает тип данных объекта.
  • Функция isinstance() проверяет принадлежность объекта определённому типу данных.

Задания для самопроверки

1. Чем отличается сильная типизация от слабой?

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

2. Что понимается под динамической типизацией в Python?

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

3. Используйте аннотации типов и создайте переменную author со значением "Сьюзен Коллинз", переменную book_titles со значением ["Голодные игры", "The Hunger Games"] и переменную year со значением 2010.

author: str = "Сьюзен Коллинз"
book_titles: list = ["Голодные игры", "The Hunger Games"]
year: int = 2010

4. При изменении значения переменной числового типа будет ли изменён её идентификатор?

Да, так как будет создан новый объект в памяти.

5. Определите типы следующих переменных:

email = "admin@mail.ru"
snow = False
clothes = ("Брюки", "Рубашка", "Галстук")
points = {"x", "y", "z"}
page = 125
meal = {"Завтрак", "Обед", "Ужин"}
temperature = {"01.01.2024": -25, "02.01.2024": -26, "03.01.2024": -23}
email  = "admin@mail.ru"  # Строка
print(type(email)) 
# Вывод: <class 'str'>

snow = False  # Логический тип
print(type(snow)) 
# Вывод: <class 'bool'>

clothes = ("Брюки", "Рубашка", "Галстук")  # Кортеж
print(type(clothes)) 
# Вывод: <class 'tuple'>

points = {"x", "y", "z"}  # Множество
print(type(points)) 
# Вывод: <class 'set'>

height = 12.5  # Число с плавающей точкой
print(type(height)) 
# Вывод: <class 'float'>

meal = ["Завтрак", "Обед", "Ужин"]  # Список
print(type(meal)) 
# Вывод: <class 'list'>

temperature = {"01.01.2024": -25, "02.01.2024": -26}  # Словарь
print(type(temperature)) 
# Вывод: <class 'dict'>