Рубрики
Без рубрики

Музные против неизменных объектов в Python – визуальное и практическое руководство

Автор оригинала: Omer Rosenbaum.

Python – это удивительный язык. Из-за его простоты многие люди выбирают его как их первый язык программирования.

Опытные программисты также используют Python все время, благодаря своему широкому сообществу, изобилия пакетов и прозрачного синтаксиса.

Но есть один вопрос, который, кажется, запутает новичков, а также некоторые опытные разработчики: объекты Python. В частности, разница между Meatable и неизменный объекты.

В этом посте мы будем углубить наши знания о объектах Python, изучать разницу между Meatable и неизменный Объекты и посмотрите, как мы можем использовать Переводчик Чтобы лучше понять, как работает Python.

Мы будем использовать важные функции и ключевые слова, такие как ID и это и мы поймем разницу между х и х это y Отказ

Вы за это? Давайте начнем.

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

Мы можем использовать наш переводчик для проверки того, что:

>>> isinstance(1, object)
True

>>> isinstance(False, object)
True

def my_func():
   return "hello"
   
>>> isinstance(my_func, object)
True

У Python есть встроенная функция, ID , который возвращает адрес объекта в память. Например:

>>> x = 1
>>> id(x)
1470416816

Выше мы создали объект по имени х и назначил его значение 1 Отказ Затем мы использовали ID (X) и обнаружил, что этот объект найден по адресу 1470416816 в памяти.

Это позволяет нам проверить интересные вещи о Python. Допустим, мы создадим две переменные в Python – один по имени х и один по имени y – и назначьте им одинаковое значение. Например, здесь:

>>> x = "I love Python!"
>>> y = "I love Python!"

Мы можем использовать оператор равенства ( == ), чтобы убедиться, что они действительно имеют одинаковое значение в глазах Python:

>>> x == y
True

Но эти тот же объект в памяти? Теоретически, здесь могут быть два очень разных сценария.

Согласно сценарию (1) У нас действительно есть два разных объекта, один по имени х и другой по имени y , что просто имеет одинаковое значение.

Тем не менее, это также может быть так, что Python фактически хранит здесь только один объект, который имеет два имена, которые ссылаются на него – как показано в сценарии (2) :

Мы можем использовать ID Функция, представленная выше, чтобы проверить это:

>>> x = "I love Python!"
>>> y = "I love Python!"
>>> x == y
True

>>> id(x)
52889984

>>> id(y)
52889384

Так как мы можем видеть, поведение Python соответствует сценарию (1), описанному выше. Хотя …| х В этом примере (то есть x и y имеют одинаковые ценности ), они разные объекты в памяти. Это потому, что ID (X) (Y) , как мы можем проверить явно:

>>> id(x) == id(y)
False

Существует более короткий способ составить сравнение выше, и это использовать Python это оператор. Проверка ли х это y такой же, как проверять ID (X) (Y) , что означает ли х и y Тот же объект в памяти:

>>> x == y
True

>>> id(x) == id(y)
False

>>> x is y
False

Это проливает свет на важное различие между оператором равенства == и оператор идентичности это Отказ

Как вы можете видеть в примере выше, он полностью возможен для двух имен в Python ( x и y ), чтобы быть связаны с двумя разными объектами (и, таким образом, x y y False ), где эти два объекта имеют одинаковое значение (так что x это True ).

Как мы можем создать другую переменную, которая указывает на тот же объект, что х указывает на? Мы можем просто использовать оператор назначения = , вот так:

>>> x = "I love Python!"
>>> z = x

Чтобы убедиться, что они действительно указывают на тот же объект, мы можем использовать это Оператор:

>>> x is z
True

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

>>> id(x)
54221824

>>> id(z)
54221824

И, конечно, у них такое же значение, поэтому мы ожидаем х вернуть Правда также:

>>> x == z
True

Мы сказали, что все в Python – это объект, но между объектами существует важное различие. Некоторые объекты являются Meatable Пока некоторые из них неизменный Отказ

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

Неизменные объекты в Python

Для некоторых типов в Python, как только мы создали экземпляры этих типов, они никогда не меняются. Они неизменный Отказ

Например, int Объекты неизменяются в Python. Что произойдет, если мы попытаемся изменить значение int объект?

>>> x = 24601
>>> x
24601

>>> x = 24602
>>> x
24602

Ну, кажется, что мы изменили х успешно. Это именно там, где многие люди запутались. Что именно произошло под капотом здесь? Давайте использовать ID Для дальнейшего расследования:

>>> x = 24601
>>> x
24601

>>> id(x)
1470416816

>>> x = 24602
>>> x
24602

>>> id(x)
1470416832

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

Так что после назначения 24601 к х Используя х У нас было следующее государство:

И после использования х Мы создали новый объект и связали имя х к этому новому объекту. Другой объект со значением 24601 больше не доходит до х (или любое другое имя в этом случае):

Всякий раз, когда мы назначаем новое значение имени (в приведенном выше примере – x ), который связан с int Объект, мы фактически изменим связывание этого имени другому объекту.

То же самое относится к кортеж S, строки ( стр. объекты), а Bool S, а также. Другими словами, int (и другие типы номеров, такие как Float ), кортеж , Bool и утра Объекты – это неизменный Отказ

Давайте проверим эту гипотезу. Что произойдет, если мы создадим кортеж Объект, а затем дайте ему другое значение?

>>> my_tuple = (1, 2, 3)
>>> id(my_tuple)
54263304

>>> my_tuple = (3, 4, 5)
>>> id(my_tuple)
56898184

Как и int Объект, мы видим, что наше назначение фактически изменило объект, которое название my_tuple связан с.

Что произойдет, если мы попытаемся изменить один из кортеж элементы?

>>> my_tuple[0] = 'a new value'
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment

Как мы видим, Python не позволяет нам модифицировать my_tuple Содержание, как это неизменно.

Музные объекты в Python

Некоторые типы в Python могут быть изменены после создания, и они называются Meatable Отказ Например, мы знаем, что мы можем изменить содержимое a Список объект:

>>> my_list = [1, 2, 3]
>>> my_list[0] = 'a new value'
>>> my_list
['a new value', 2, 3]

Значит ли это, что мы на самом деле создали новый объект при назначении нового значения первого элемента my_list ? Опять же, мы можем использовать ID проверить:

>>> my_list = [1, 2, 3]
>>> id(my_list)
55834760

>>> my_list
[1, 2, 3]

>>> my_list[0] = 'a new value'
>>> id(my_list)
55834760

>>> my_list
['a new value', 2, 3]

Так что наше первое назначение my_list = [1, 2, 3] создал объект по адресу 55834760 , со значениями 1 , 2 и 3 :

Затем мы изменили первый элемент этого Список Объект, использующий my_list [0] то есть – без создания нового Список объект:

Теперь давайте создадим два имени – х и y , оба связаны с той же Список объект. Мы можем проверить, что используя это или явно проверяя их ID S:

>>> x = y = [1, 2]
>>> x is y
True

>>> id(x)
18349096

>>> id(y)
18349096

>>> id(x) == id(y)
True

Что происходит сейчас, если мы используем x.append (3) ? То есть, если мы добавим новый элемент ( 3 ) к объекту по имени х ?

Будет ли х Изменено? Будет ли y ?

Ну, как мы уже знаем, они в основном два имена того же объекта:

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

>>> x.append(3)
>>> x
[1, 2, 3]

>>> y
[1, 2, 3]

Обратите внимание, что х и y иметь то же самое ID Как и раньше – как они все еще связаны с тем же Список объект:

>>> id(x)
18349096

>>> id(y)
18349096

В дополнение к Список S, другие типы Python, которые являются Musable, включают Установить S и Диктовать с.

Словари ( Dict Объекты) обычно используются в Python. В качестве быстрого напоминания мы определяем их так:

my_dict = {"name": "Omer", "number_of_pets": 1}

Затем мы можем получить доступ к конкретному элементу его ключевым именем:

>>> my_dict["name"]
'Omer'

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

>>> my_dict["name"] = "John"
>>> my_dict["name"]
'John'

Интересно отметить, что Ключи словаря должны быть неизменными :

>>> my_dict = {[1,2]: "Hello"}
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unhashable type: 'list'

Почему это так?

Рассмотрим следующий гипотетический сценарий (Примечание: фрагмент ниже не может быть запущен в Python):

>>> x = [1, 2]
>>> y = [1, 2, 3]
>>> my_dict = {x: 'a', y: 'b'}

До сих пор все не кажется плохой. Мы предполагаем, что если мы доступм my_dict С ключом [1, 2] мы получим соответствующее значение «А» и если мы доступ к ключу [1, 2, 3] мы получим ценность 'b' Отказ

Теперь, что бы произошло, если мы попытаемся использовать:

>>> x.append(3)

В этом случае х будет иметь значение [1, 2, 3] и y также будет иметь значение [1, 2, 3] Отказ Что мы должны получить, когда мы просим my_dict [[1, 2, 3]] ? Будет ли это «А» или 'b' ? Чтобы избежать таких случаев, Python просто не позволяет смешивать ключи словаря.

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

Ниже мы определяем Список (A Metable объект) и A кортеж (AN Immutable объект). Список включает в себя кортеж и кортеж включает в себя Список :

>>> my_list = [(1, 1), 2, 3]
>>> my_tuple = ([1, 1], 2, 3)
>>> type(my_list)


>>> type(my_list[0])


>>> type(my_tuple)


>>> type(my_tuple[0])

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

(1) >>>

(2) >>>

В заявлении (1), что мы пытаемся сделать, это изменить my_list первый элемент, то есть кортеж Отказ Так как кортеж это неизменный Эта попытка суждена потерпеть неудачу:

>>> my_list[0][0] = 'Changed!'
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment

Обратите внимание, что то, что мы пытались сделать, это не Измените список, а скорее – измените содержимое своего первого элемента.

Давайте рассмотрим заявление (2). В этом случае мы доступны my_tuple первый элемент, который бывает Список и измените это. Давайте дальше рассмотрим этот случай и посмотрим на адреса этих элементов:

>>> my_tuple = ([1, 1], 2, 3)
>>> id(my_tuple)
20551816

>>> type(my_tuple[0])


>>> id(my_tuple[0])
20446248

Когда мы меняемся my_tuple [0] [0] Мы на самом деле не меняем my_tuple вообще! Действительно, после изменения, my_tuple Первый элемент все равно будет объектом, адрес которого в памяти 20446248 Отказ Мы делаем, однако, измените значение этого объекта:

>>> my_tuple[0][0] = 'Changed!'
>>> id(my_tuple)
20551816

>>> id(my_tuple[0])
20446248

>>> my_tuple
(['Changed!', 1], 2, 3)

Так как мы модифицировали только значение my_tuple [0] , что является смешным Список Объект, эта операция была действительно разрешена Python.

В этом посте мы узнали о объектах Python. Мы сказали, что в Python Все это объект и должен использовать ID и это Чтобы углубить наше понимание того, что происходит под капотом при использовании Python для создания и модификации объектов.

Мы также узнали разницу между Meatable Объекты, которые могут быть изменены после создания, а неизменный объекты, которые не могут.

Мы видели, что когда мы просим Python изменить неизменного объекта, который связан с определенным именем, мы фактически создаем новый объект и связываете это имя для него.

Затем мы узнали, почему словарные ключи должны быть неизменный в питоне.

Понимание того, как Python «Wees» объекты – это ключ, чтобы стать лучшим программистом Python. Я надеюсь, что этот пост помог вам в вашем путешествии к освоению Python.

Омер Розенбаум , Swimm главный технический директор. Эксперт по кибер-тренажению и основатель академии безопасности контрольно-пропускных пунктов. Автор Компьютерные сети (на иврите) Отказ Посетите мой YouTube Channel Отказ