Строки в python неизменяемы что это значит
Почему строки Python неизменяемы? Рекомендации по их использованию
6 ответов
когда вы получите строку, вы будете уверены, что она останется прежней. Предположим, что вы построите Foo как показано ниже со строковым аргументом, а затем измените строку; затем Foo имя внезапно изменится:
с изменяемыми строками, вам придется делать копии все время, чтобы предотвратить плохие вещи не случилось.
это также позволяет удобство, что один символ не отличается от строки длины один, так что все строковые операторы применяются также к символам.
что касается программирования с неизменяемыми строками, просто привыкайте относиться к ним так же, как вы относитесь к числам: как значения, а не как объекты. Изменение первой буквы name будет
неизменяемые строки значительно упрощают выделение памяти по сравнению со строками C: вы не догадываетесь о длине и чрезмерном выделении, надеясь, что вы достаточно выделили.
они более безопасны: вы можете никогда есть буфер переполнен, как вы можете в C.
существует только один изменяемый вариант использования строки.
все другие варианты использования строк (конкатенация, поиск и т. д., п.) изменчивость не имеет значения. Во всех остальных случаях изменчивость не имеет значения.
Если вы хотите заменить символ или подстроку в Python, вы просто создаете новую строку
это единственный код, который является новым или отличительным.
по причинам, которые я не понимаю, кажется важным добавить следующее.
» есть другие способы избежать переполнения строкового буфера, чем неизменяемый веревка.»
для целей этого вопроса (в частности, о Python) неизменяемые строки имеют приятное следствие отсутствия переполнения буфера. Для других языков применяются другие принципы, правила и нюансы.
Python 3: изменяемый, неизменяемый…
Многие из нас считают Python прекрасным языком программирования. В нем легко разобраться, он очень хорошо читается, а код на нем легко поддерживать. Но основная причина простоты этого языка состоит в том, что под капотом у него есть очень много всего. И хотя многие люди просто знают, что в языке есть и сложные вещи, и им этого достаточно, понимание тонкостей поможет вам избежать появления многих багов в ваших программах. Цель этой статьи — познакомить вас с этими тонкостями.
Объекты
Давайте начнем с краеугольного камня Python — с объектов. Объектом является буквально все. Ваш модуль это объект, функция — объект, число — тоже объект. Объекты это просто экземпляры классов.
Чтобы понять эту концепцию, мы можем представить, что объекты — это отдельные люди, а классы — это группы, к которым эти люди принадлежат. Скажем, все мы — люди (класс human), но я — уникальный индивид (экземпляр класса human).
В Python все является объектом. Каждый объект имеет собственный тип данных и внутреннее состояние (данные). Давайте для начала уясним, как данные хранятся в памяти. Для этого рассмотрим пару примеров.
Пример 1
Пример 2
Идентичность и тип
Функция id() возвращает идентификатор указанной вами переменной. Каждая переменная в Python ссылается на какой-нибудь объект, а идентификатор переменной это целое число, «привязанное» к конкретному объекту. В реализации CPython это число — адрес объекта в памяти. Идентификатор объекта позволяет разграничить случаи, когда переменные идентичны, и когда они ссылаются на один и тот же объект. Для определения идентичности мы можем использовать «==», а «is» используется для определения того, указывают ли переменные на один и тот же объект.
Но все станет куда более странно, если мы сделаем вот так:
Вероятно, вы думаете: «Погодите, погодите! Что?! Ведь пару секунд назад, когда мы рассматривали списки, я понял, что они разные. А эти тогда почему одинаковые?» Чтобы ответить на этот вопрос, мы должны углубиться в предмет изменяемости.
Изменяемые объекты
Итак, что же такое изменяемость (мутабельность)? Выражаясь простым языком, это способность мутировать — или изменять объект. К изменяемым (мутабельным) типам в Python относятся списки, множества, словари и bytearrays (массивы байтов). Давайте рассмотрим пример с нашим старым добрым списком. Мы можем добавлять в него элементы:
Мы можем удалять из него элементы:
Как уже говорилось, в Python все является объектом. Поэтому каждый элемент в списке это тоже объект. Если мы приглядимся, все опять станет очень странным:
Почему идентификатор l[1] изменился? Идентификатор всего списка остался неизменным, хотя мы изменили его значения, но почему же изменился идентификатор его элемента? Потому что числа и строки неизменяемы (не мутабельны).
Неизменяемые объекты
Неизменяемость это противоположность изменяемости (логично). Если объект неизменяемый, это значит, что вы не можете менять его содержимое. К встроенным неизменяемым типам относятся целые числа, числа с плавающей точкой, комплексные числа, строки, кортежи, frozenset-ы и байты.
В приведенном выше примере объект список изначально содержал ссылки на объекты «1», «2» и «3». Хотя мы не можем изменить сам объект (цифру 2), можно изменить список за счет изменения хранящейся в нем ссылки. Теперь список содержит ссылку на объект «Hello». Другими словами, произошло переназначение. И хотя увеличивать неизменяемый объект нельзя, мы можем сделать так:
Кажется, что мы добавили «World» к «Hello», но на самом деле произошло примерно следующее:
Было вычислено значение s («Hello») плюс “ World”, и переменная s получила ссылку на новый объект. Похожий процесс происходит при добавлении чисел:
Но если вы попытаетесь изменить элемент в неизменяемом наборе, интерпретатор возбудит исключение:
Аналогично — хотя удалить элемент в неизменяемом объекте нельзя, вы можете взять срез объекта, в результате чего вернется новый объект, содержащий нужные значения:
Поскольку Python должен создавать отдельный объект для каждого уникального неизменяемого значения (что занимает много памяти), интерпретатор разумным образом оптимизирует создание объектов. Эта оптимизация происходит за счет использования одинаковых ссылок для неизменяемых объектов, таких как строки:
Преаллокация в Python
А теперь домашнее задание для вас:
Почему это важно?
При присваивании значений переменным очень важно понимать разницу между изменяемыми и неизменяемыми объектами. Изменяемые объекты имеют пару тузов в рукаве. Мы уже рассматривали этот пример:
А что, если мы хотим создать копию объекта, чтобы при внесении изменений не волноваться о том, что это затронет оригинал? Мы можем взять срез списка, при этом вернется новый объект (так же, как когда мы брали срез неизменяемого объекта):
Добавление элементов в списки тоже может быть хитрой штукой. В Python то, что находится в левой части выражения присваивания, получает ссылку на все, что вычисляется в правой. Поэтому:
Мы видим, что объект остался прежним. Это замещающее присваивание — эквивалент добавления элементов в список. Но поскольку иммутабельные объекты не могут быть изменены, выражения a += b и a = a + b будут работать одинаково и аналогично нашему примеру «Hello World».
Передача аргументов в функции
В других языках программирования переменные часто передаются одним из двух способов:
Но Python в этом плане уникален. Python передает ссылку на объект. Аналогично тому как мы делали переменную y псевдонимом переменной x ( x = y ), при передаче переменной в функцию аргумент функции становится псевдонимом для ссылки на объект.
Это означает, что если внутри функции произойдет новое присваивание, это не изменит оригинальную переменную, переданную в функцию. Поскольку иммутабельные типы не могут быть изменены, никакое изменение переменной внутри функции не сохранится:
Но поскольку списки мутабельны, их содержимое изменять можно:
Обратите внимание, что ссылка на список остается той же на протяжении всей программы. Тем не менее, если бы мы переприсвоили значение l внутри функции, это не затронуло бы исходный список.
Исключения в неизменяемости
Не все неизменяемые объекты на самом деле неизменяемы. Да, все очень запутанно, но сейчас разберемся.
Как уже говорилось, в Python контейнеры типа кортежей неизменяемы. Это значит, что значение tuple не может меняться после того, как кортеж создан. Но «значение» кортежа на самом деле является последовательностью имен с неизменяемыми привязками к объектам. Главное, что нужно понять, это что неизменяемы именно привязки, а не сами объекты.
Кортеж t содержит элементы с разными типами данных. Первый элемент — неизменяемая строка, а второй — изменяемый список. Сам кортеж неизменяемый (нет никаких методов для изменения его содержимого). Аналогично и строка неизменяема, потому что у строк нет никаких методов для их изменения. Но объект список имеет методы, с помощью которых его можно изменить, так что он изменяемый. Это мелочь, но важная: «значение» неизменяемого объекта не может меняться, но объекты, из которых он состоит, — могут.
Заключение
Понимание тонкостей языка может быть чрезвычайно полезным. Многие программисты не уделяют достаточно времени тому, чтобы хорошенько изучить языки, которыми пользуются на постоянной основе. Но близкое знакомство с Python — отличный способ избежать багов.
Кроме того, самодисциплина, позволяющая вам сесть и изучить, что происходит под капотом языка, — сама по себе отличная вещь, которая сослужит вам прекрасную службу в вашей программистской карьере.
Изменяемые vs. неизменяемые типы данных в Python
Python считается одним из самых удивительных языков программирования. Многие люди выбирают его в качестве первого языка из-за его элегантности и простоты. Благодаря широкому сообществу, избытку пакетов и согласованности синтаксиса, опытные профессионалы также используют Python. Тем не менее, существует одна вещь, которая раздражает как новичков, так и некоторых профессиональных разработчиков – объекты Python.
Изменяемые vs. неизменяемые объекты
Как известно, объектом в Python является абсолютно все, а каждый объект относится к какому-либо типу данных. Типы данных бывают изменяемые и неизменяемые (англ. mutable и immutable). К неизменяемым относятся целые числа (int), числа с плавающей запятой (float), булевы значения (bool), строки (str), кортежи (tuple). К изменяемым — списки (list), множества (set), байтовые массивы (byte arrays) и словари (dict).
Функции id() и type()
Разобраться с изменяемостью типов данных нам помогут встроенные функции и операторы Python.
Встроенный метод id() возвращает идентификатор объекта в виде целого числа. Это целое число обычно относится к месту хранения объекта в памяти. Встроенная функция type() возвращает тип объекта.
Неизменяемые типы данных
Давайте рассмотрим некоторые неизменяемые типы.
Целые числа (int)
Строки (str)
То же самое верно и для строкового типа данных. Мы не можем изменить существующую переменную, вместо этого мы должны создать новую с тем же именем.
Кортежи (tuple)
Давайте разберем кортежи. Мы определили кортеж с 4 значениями. Воспользуемся функцией id() для вывода его адреса. Если мы захотим изменить значение первого элемента, то получим ошибку TypeError. Это означает, что кортеж не поддерживает присвоение или обновление элементов.
С другой стороны, мы можем обновить весь кортеж, задав его с нуля. После этого мы увидим новые значения элементов кортежа и новый адрес.
Числа с плавающей запятой (float)
Если же мы обновим float, переопределив его, то при вызове получим новое значение и новый адрес.
Изменяемые типы данных
Теперь давайте рассмотрим некоторые изменяемые типы.
Списки (list)
Определим список с именем x и добавим в него некоторые значения. После этого обновим список: присвоим новое значение элементу с индексом 1. Можем заметить, что операция успешно выполнилась.
Вышеописанные действия являются простым и базовым примером модификации. Чтобы проверить изменчивость на более глубоком уровне, давайте рассмотрим тот же пример с небольшими изменениями.
Теперь добавим новое значение к списку x и проверим обновленный вывод.
Словари (dict)
Словари — часто используемый тип данных в Python. Давайте посмотрим на их изменчивость.
Определим словарь под именем dict с тремя ключами и их значениями. Когда мы распечатаем его, отобразится все его содержимое. Можно распечатать каждое значение словаря отдельно, а также использовать ключи вместо индексов. Подробнее о добавлении элементов в словарь вы можете узнать тут.
Списки и кортежи: наглядный пример изменяемых и неизменяемых объектов
Давайте по отдельности определим список и кортеж. Убедимся, что в кортеже есть значение типа список, а в списке есть значение типа кортеж.
Нулевой элемент кортежа – список. Давайте попробуем изменить какой-то из элементов списка, указав его индекс. Например, можно поменять в нулевом элементе кортежа (т.е. в списке) нулевой элемент. Нам успешно удается это сделать, потому что список – изменяемый объект, даже если он находится в кортеже.
Если же, наоборот, кортеж находится в списке, то вы не сможете поменять элемент этого кортежа, хотя он и находится в изменяемом списке. Ведь сам кортеж неизменяем. Поэтому такие преобразования невозможны.
Заключение
Мы разобрали различия между изменяемым и неизменяемым объектами в Python. Стоит понимать, что всё в Python называется объектами. И главное различие между ними – являются они изменяемыми или неизменяемыми.
Изменяемость объектов в Python
Хочешь знать больше о Python?
Подпишись на наш канал о Python в Telegram!
Многие из нас считают Python прекрасным языком программирования. В нем легко разобраться, он очень хорошо читается, а код на нем легко поддерживать. Но основная причина простоты этого языка состоит в том, что под капотом у него есть очень много всего, — пишет сайт pythonist.ru.
И хотя многие люди просто знают, что в языке есть и сложные вещи, и им этого достаточно, понимание тонкостей поможет вам избежать появления многих багов в ваших программах. Цель этой статьи — познакомить вас с этими тонкостями.
Объекты
Давайте начнем с краеугольного камня Python — с объектов. Объектом является буквально все. Ваш модуль это объект, функция — объект, число — тоже объект. Объекты это просто экземпляры классов.
Чтобы понять эту концепцию, мы можем представить, что объекты — это отдельные люди, а классы — это группы, к которым эти люди принадлежат. Скажем, все мы — люди (класс human), но я — уникальный индивид (экземпляр класса human).
В Python все является объектом. Каждый объект имеет собственный тип данных и внутреннее состояние (данные). Давайте для начала уясним, как данные хранятся в памяти. Для этого рассмотрим пару примеров.
Пример 1
Пример 2
Идентичность и тип
Функция id() возвращает идентификатор указанной вами переменной. Каждая переменная в Python ссылается на какой-нибудь объект, а идентификатор переменной это целое число, «привязанное» к конкретному объекту. В реализации CPython это число — адрес объекта в памяти. Идентификатор объекта позволяет разграничить случаи, когда переменные идентичны, и когда они ссылаются на один и тот же объект. Для определения идентичности мы можем использовать «==», а «is» используется для определения того, указывают ли переменные на один и тот же объект.
Но все станет куда более странно, если мы сделаем вот так:
Вероятно, вы думаете: «Погодите, погодите! Что?! Ведь пару секунд назад, когда мы рассматривали списки, я понял, что они разные. А эти тогда почему одинаковые?» Чтобы ответить на этот вопрос, мы должны углубиться в предмет изменяемости.
Изменяемые объекты
Итак, что же такое изменяемость (мутабельность)? Выражаясь простым языком, это способность мутировать — или изменять объект. К изменяемым (мутабельным) типам в Python относятся списки, множества, словари и bytearrays (массивы байтов). Давайте рассмотрим пример с нашим старым добрым списком. Мы можем добавлять в него элементы:
Мы можем удалять из него элементы:
Как уже говорилось, в Python все является объектом. Поэтому каждый элемент в списке это тоже объект. Если мы приглядимся, все опять станет очень странным:
Почему идентификатор l[1] изменился? Идентификатор всего списка остался неизменным, хотя мы изменили его значения, но почему же изменился идентификатор его элемента? Потому что числа и строки неизменяемы (не мутабельны).
Неизменяемые объекты
Неизменяемость это противоположность изменяемости (логично). Если объект неизменяемый, это значит, что вы не можете менять его содержимое. К встроенным неизменяемым типам относятся целые числа, числа с плавающей точкой, комплексные числа, строки, кортежи, frozenset-ы и байты.
В приведенном выше примере объект список изначально содержал ссылки на объекты «1», «2» и «3». Хотя мы не можем изменить сам объект (цифру 2), можно изменить список за счет изменения хранящейся в нем ссылки. Теперь список содержит ссылку на объект «Hello». Другими словами, произошло переназначение. И хотя увеличивать неизменяемый объект нельзя, мы можем сделать так:
Кажется, что мы добавили «World» к «Hello», но на самом деле произошло примерно следующее:
Было вычислено значение s («Hello») плюс “ World”, и переменная s получила ссылку на новый объект. Похожий процесс происходит при добавлении чисел:
Но если вы попытаетесь изменить элемент в неизменяемом наборе, интерпретатор возбудит исключение:
Аналогично — хотя удалить элемент в неизменяемом объекте нельзя, вы можете взять срез объекта, в результате чего вернется новый объект, содержащий нужные значения:
Поскольку Python должен создавать отдельный объект для каждого уникального неизменяемого значения (что занимает много памяти), интерпретатор разумным образом оптимизирует создание объектов. Эта оптимизация происходит за счет использования одинаковых ссылок для неизменяемых объектов, таких как строки:
Преаллокация в Python
А теперь домашнее задание для вас:
Почему это важно?
При присваивании значений переменным очень важно понимать разницу между изменяемыми и неизменяемыми объектами. Изменяемые объекты имеют пару тузов в рукаве. Мы уже рассматривали этот пример:
А что, если мы хотим создать копию объекта, чтобы при внесении изменений не волноваться о том, что это затронет оригинал? Мы можем взять срез списка, при этом вернется новый объект (так же, как когда мы брали срез неизменяемого объекта):
Добавление элементов в списки тоже может быть хитрой штукой. В Python то, что находится в левой части выражения присваивания, получает ссылку на все, что вычисляется в правой. Поэтому:
Мы видим, что объект остался прежним. Это замещающее присваивание — эквивалент добавления элементов в список. Но поскольку иммутабельные объекты не могут быть изменены, выражения a += b и a = a + b будут работать одинаково и аналогично нашему примеру «Hello World».
Передача аргументов в функции
В других языках программирования переменные часто передаются одним из двух способов:
Но Python в этом плане уникален. Python передает ссылку на объект. Аналогично тому как мы делали переменную y псевдонимом переменной x ( x = y ), при передаче переменной в функцию аргумент функции становится псевдонимом для ссылки на объект.
Это означает, что если внутри функции произойдет новое присваивание, это не изменит оригинальную переменную, переданную в функцию. Поскольку иммутабельные типы не могут быть изменены, никакое изменение переменной внутри функции не сохранится:
Но поскольку списки мутабельны, их содержимое изменять можно:
Обратите внимание, что ссылка на список остается той же на протяжении всей программы. Тем не менее, если бы мы переприсвоили значение l внутри функции, это не затронуло бы исходный список.
Исключения в неизменяемости
Не все неизменяемые объекты на самом деле неизменяемы. Да, все очень запутанно, но сейчас разберемся.
Как уже говорилось, в Python контейнеры типа кортежей неизменяемы. Это значит, что значение tuple не может меняться после того, как кортеж создан. Но «значение» кортежа на самом деле является последовательностью имен с неизменяемыми привязками к объектам. Главное, что нужно понять, это что неизменяемы именно привязки, а не сами объекты.
Кортеж t содержит элементы с разными типами данных. Первый элемент — неизменяемая строка, а второй — изменяемый список. Сам кортеж неизменяемый (нет никаких методов для изменения его содержимого). Аналогично и строка неизменяема, потому что у строк нет никаких методов для их изменения. Но объект список имеет методы, с помощью которых его можно изменить, так что он изменяемый. Это мелочь, но важная: «значение» неизменяемого объекта не может меняться, но объекты, из которых он состоит, — могут.
Заключение
Понимание тонкостей языка может быть чрезвычайно полезным. Многие программисты не уделяют достаточно времени тому, чтобы хорошенько изучить языки, которыми пользуются на постоянной основе. Но близкое знакомство с Python — отличный способ избежать багов.
Кроме того, самодисциплина, позволяющая вам сесть и изучить, что происходит под капотом языка, — сама по себе отличная вещь, которая сослужит вам прекрасную службу в вашей программистской карьере.