Введение

Python трезв, ясен и хорошо организован. Это действительно элегантный язык.

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

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

Когда мы начинаем изучать Python, все ресурсы, с которыми мы сталкиваемся, говорят об «объекте». Ну да, в 1646-й раз: в Python все является объектом, как следует из его собственного определения: «Python — это язык объектно-ориентированного программирования (ООП)». Классы, модули, экземпляры, переменные, методы, строки, структуры данных, такие как списки, являются объектами. Объект – это просто объект, который содержит данные вместе со связанными метаданными и/или функциями. Каждый объект имеет свой идентификатор, тип и свое внутреннее состояние (данные).

Теперь, когда мы это поняли, давайте углубимся в это!

ID и ТИП

Как мы можем узнать, является ли объект изменяемым или неизменяемым?

По их идентификатору и их типу. Тадаааа!

id

У каждого объекта есть свой собственный уникальный идентификатор (ID), как у вас или вашего соседа. Каждый раз, когда создается экземпляр объекта (или рождается ребенок), ему присваивается уникальный идентификатор. Это уникальная идентификация объекта, хранящегося в памяти, которая позволяет отличить один объект от другого. Он остается постоянным в течение всего срока службы и не может быть изменен. Чтобы узнать, что такое идентификатор объекта, мы используем встроенную функцию id(object). Он принимает один параметр и возвращает уникальное целочисленное значение этого объекта.

Мы используем «==», чтобы проверить, идентичны ли два объекта, и оператор «есть», чтобы сравнить их идентичность, он вернет True, если оба объекта ссылаются на одно и то же значение.

Давай попробуем:

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

В нашем примере мы видим, что они оба ссылаются на один и тот же объект 27, и для переменной b не было выделено никакой другой памяти. Это потому, что наши объекты a и b имеют одинаковую идентичность: a действительно b!

тип

В Python также есть встроенная функция type(). Если передается только один аргумент type(object), он возвращает тип объекта. Если переданы три аргумента type(object, bases, dict), он возвращает объект нового типа.

Давайте еще поиграем с идентификатором и типом (да, потому что Python — это весело!):

"Хм ?" Вы могли бы сказать. Я знаю, у меня была такая же реакция, когда я впервые столкнулся с id и list. Настало время, ребята… время для изменяемых и неизменяемых объектов! Без лишних слов, давайте объясним это.

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

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

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

Некоторыми изменяемыми объектами являютсясписок, словарь, набор, массив, пользовательские классы.

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

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

Неизменными объектами являются числа (целое число, число с плавающей запятой, комплекс), строка, кортеж, фиксированный набор, байты.

Попробуем изменить super_tuple:

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

my_object кажется изменяемым, но мы сказали, что строка неизменна, верно? Ну, на самом деле нет. Если мы посмотрим на идентификаторы, то увидим, что они изменены, а это означает, что когда мы второй раз присваиваем новое значение new_object, нашему объекту присваивается новый идентификатор.

Исключение!

Осторожно, кортеж, состоящий, например, из строк и списка, неизменяем, но список остается изменяемым.

Почему это важно и насколько по-разному Python обрабатывает изменяемые и неизменяемые объекты?

Выделение памяти

В нашем первом фрагменте кода мы видели, что значение будет иметь только одну копию в памяти, и все переменные, имеющие это значение, будут ссылаться на это место в памяти. В приведенном ниже примере объекты a, b и c ссылаются на одно и то же значение 10. Это потому, что Python оптимизирует свою память. Это большая разница с языком C, в котором новое пространство памяти выделяется каждый раз, когда мы объявляем переменную. Это работает для всех неизменяемых объектов.

Да, Python умен и умеет экономить память!

Предварительное выделение памяти

В качестве оптимизации CPython предварительно выделяет некоторые целые числа, которые считаются малыми, поскольку они используются чаще всего, и будет повторно использовать их вместо создания экземпляров дубликатов. В Python 3.4 числа от -5 до 256 выделены заранее. Когда мы создаем целое число в этом диапазоне, мы на самом деле просто получаем ссылку на существующий объект в памяти. Это позволяет получить быстрый доступ к часто используемым int. В исходном коде объекта Python int определены макросы с именами NSMALLPOSINTS (257) и NSMALLNEGINTS (-5):

При объявлении новой переменной важен выбор между изменяемой и неизменной. Мы используем изменяемые объекты, когда нам нужно изменить состояние нашего объекта. Неизменяемые объекты важны, когда нам нужна гарантия того, что наш объект не будет изменен.

Давайте изучим другой пример:

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

Однако, если мы назначим фрукты пище:

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

Как аргументы передаются функциям и что это означает для изменяемых и неизменяемых объектов?

Ключевым моментом здесь является знание того, как аргументы передаются функциям. В некоторых языках программирования, таких как C, аргументы передаются либо по ссылке, либо по значению. Python использует систему, известную как «Вызов по ссылке на объект» или «Вызов по назначению»:

"Ссылки на объекты передаются по значению". Нееет, не уходите, попробую объяснить просто.

Во-первых, давайте напомним, что такое вызов по ссылке и вызов по значению:

Звонок по ссылке

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

Вызов по значению

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

Вызов по назначению

В Питоне:

  • если объект неизменяем, то измененное значение недоступно вне функции.
  • если объект является изменяемым, то измененное значение доступно вне функции.

Вот пример:

Краткое содержание

  • В Python все представлено объектами или отношениями между объектами.
  • У каждого объекта есть ID, тип и значение.
  • Идентификатор объекта никогда не меняется после того, как он был создан. Вы можете думать об этом как о адресе объекта в памяти.
  • Объекты, чье значение может быть изменено после их создания, называются изменяемыми. Объекты, чье значение не может быть изменено, называются называется неизменяемым.
  • Python использует систему, известную как «Вызов по ссылке на объект» или «Вызов по назначению». Если вы передаете функции такие аргументы, как неизменяемые объекты, передача аналогична вызову по значению. В то время как передача изменяемых объектов может рассматриваться как вызов по ссылке.