Структур данных являются неизменяемыми python

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

Python считается одним из самых удивительных языков программирования. Многие люди выбирают его в качестве первого языка из-за его элегантности и простоты. Благодаря широкому сообществу, избытку пакетов и согласованности синтаксиса, опытные профессионалы также используют Python. Тем не менее, существует одна вещь, которая раздражает как новичков, так и некоторых профессиональных разработчиков – объекты Python.

Изменяемые и неизменяемые объекты

Как известно, объектом в Python является абсолютно все, а каждый объект относится к какому-либо типу данных. Типы данных бывают изменяемые и неизменяемые (англ. mutable и immutable). К неизменяемым относятся целые числа (int), числа с плавающей запятой (float), булевы значения (bool), строки (str), кортежи (tuple). К изменяемым — списки (list), множества (set), байтовые массивы (byte arrays) и словари (dict).

Функции id() и type()

Разобраться с изменяемостью типов данных нам помогут встроенные функции и операторы Python.

Встроенный метод id() возвращает идентификатор объекта в виде целого числа. Это целое число обычно относится к месту хранения объекта в памяти. Встроенная функция type() возвращает тип объекта.

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

Если сравнить две переменные, x и y , имеющие одинаковое значение, при помощи оператора равенства ( x == y ), он выдаст True. Но если мы при помощи того же оператора сравним идентификаторы объектов x и y (полученные с использованием функции id() ) – мы получим False. Дело в том, что во втором случае мы сравнивали адреса памяти переменных, а они разные – расположены в разных местах. Хотя значения, которые содержат эти переменные, одинаковы.

x = 'Привет!' y = 'Привет!' x == y # Получим True id(x) == id(y) # Получим False

Создадим переменную z путем присвоения ей в качестве значения переменной x . Используя оператор is , мы обнаружим, что обе переменные указывают на один и тот же объект и, соответственно, имеют одинаковые идентификаторы.

x = 'Привет!' z = x x is z # Получим True id(x) == id(z) # Получим True

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

Давайте рассмотрим некоторые неизменяемые типы.

Читайте также:  Java runnable with exception

Целые числа (int)

Давайте определим переменную x , имеющую значение 10. Встроенный метод id() используется для определения местоположения x в памяти, а type() используется для определения типа переменной. Когда мы пытаемся изменить значение x , оно успешно изменяется.

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

x = 10 print(x, type(x), id(x)) # Получим (10, int, 140727505991744)
x = 12 print(x, type(x), id(x)) # Получим (12, int, 140727505991808)

Строки (str)

То же самое верно и для строкового типа данных. Мы не можем изменить существующую переменную, вместо этого мы должны создать новую с тем же именем.

В данном примере мы определили строковую переменную x , но допустили ошибку в слове и теперь хотим исправить «ю» на «и». Однако мы получаем TypeError. Это показывает, что строковые объекты не подлежат обновлению.

x = 'Прювет!' x[2] = 'и' # Получим TypeError: 'str' object does not support item assignment

Кортежи (tuple)

Давайте разберем кортежи. Мы определили кортеж с 4 значениями. Воспользуемся функцией id() для вывода его адреса. Если мы захотим изменить значение первого элемента, то получим ошибку TypeError. Это означает, что кортеж не поддерживает присвоение или обновление элементов.

tuple1 = (1, 2, 3, 4) print(tuple1, id(tuple1)) # Получим (1, 2, 3, 4) 3240603720336

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

tuple1 = (5, 6, 7, 8) print(tuple1, id(tuple1)) # Получим (5, 6, 7, 8) 3240603720256

Числа с плавающей запятой (float)

У нас есть переменная x типа float. Используя функцию id() , мы можем узнать ее адрес. Если мы попробуем заменить элемент с индексом 1, то получим TypeError. Как и в предыдущих примерах видим, что float не поддерживает модификацию элемента.

x = 3.456 x[1] = 4 # Получим TypeError: 'float' object does not support item assignment

Если же мы обновим float, переопределив его, то при вызове получим новое значение и новый адрес.

x = 3.654 type(x), id(x) # Получим (float, 3240603166960)

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

Теперь давайте рассмотрим некоторые изменяемые типы.

Читайте также:  Код на будильник питон

Списки (list)

Определим список с именем x и добавим в него некоторые значения. После этого обновим список: присвоим новое значение элементу с индексом 1. Можем заметить, что операция успешно выполнилась.

x = ['Яблоко', 'Груша', 'Слива'] x[1] = 'Ананас' x # выведет ['Яблоко', 'Ананас', 'Слива']

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

Создадим новое имя y и свяжем его с тем же объектом списка. А теперь проверим, совпадает ли x с y . Нам вернется True. Кроме того, x и y имеют одинаковые адреса памяти.

x = y = ['Яблоко', 'Груша', 'Слива'] x is y # True id(x), id(y), id(x) == id(y) # (3240602862208, 3240602862208, True)

Теперь добавим новое значение к списку x и проверим обновленный вывод.

x.append('Персик') x # ['Яблоко', 'Груша', 'Слива', 'Персик']

Если мы теперь вызовем y , то получим тот же список, что и при вызове x . Хотя непосредственно в y мы ничего не добавляли. Это означает, что по сути мы обновляем один список объектов, у которого есть два разных имени: x и y . Оба они одинаковы и имеют один адрес в памяти даже после модификации.

y # ['Яблоко', 'Груша', 'Слива', 'Персик'] x is y, id(x) == id(y) # (True, True)

Словари (dict)

Словари — часто используемый тип данных в Python. Давайте посмотрим на их изменчивость.

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

dict = dict # Получим dict['Name'], dict['Age'], dict['Job'] # ('Алиса', 27, 'Senior Python Developer')

Давайте изменим какое-нибудь значение в нашем словаре. Например, обновим значение для ключа Name . Выведем обновленный словарь. Значение изменилось. При этом сами ключи словаря неизменяемы.

Читайте также:  основы php на BlogGood.ru

Списки и кортежи: наглядный пример изменяемых и неизменяемых объектов

Давайте по отдельности определим список и кортеж. Убедимся, что в кортеже есть значение типа список, а в списке есть значение типа кортеж.

tuple1 = ([1, 1], 2, 3) list1 = [(1, 1), 2, 3] tuple1, list1 # (([1, 1], 2, 3), [(1, 1), 2, 3])

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

tuple1[0][0] = 'Поменялся' tuple1 # (['Поменялся', 1], 2, 3)

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

list1[0][0] = 'Поменялся' list1 # Получим TypeError: 'tuple' object does not support item assignment

Заключение

Мы разобрали различия между изменяемым и неизменяемым объектами в Python. Стоит понимать, что всё в Python называется объектами. И главное различие между ними – являются они изменяемыми или неизменяемыми.

Источник

Оцените статью