Объекты являются основной конструкцией любого языка ООП, и каждый язык определяет свой собственный синтаксис для их создания, обновления и уничтожения. В Python каждый объект имеет идентификатор, тип и значение. Однако только значение объекта может изменяться с течением времени.
В этой статье мы рассмотрим эти темы:
Обычно переменные рассматриваются как коробки или контейнеры, что мешает пониманию ссылочных переменных в объектно-ориентированных языках.
Переменные Python похожи на ссылочные переменные в Java, вы можете думать о них как о метках с именами, прикрепленными к объектам.
var_one = [1, 2, 3] var_two = var_one var_one.append(4) print(var_two) # [1, 2, 3, 4]
В этом примере мы изменяем список, на который ссылается "var_one", добавляя еще один элемент. Когда мы печатаем "var_two", мы получаем тот же список.
Это означает, что "var_two" ссылается на тот же список, на который ссылается "var_one".
Ничто не мешает объекту иметь несколько меток, назначенных ему, т.е. разные переменные, ссылающиеся на один и тот же объект.
Это приводит нас к другим вопросам! Как проверить, равны ли два объекта?
В Python каждый объект имеет свой id, и его можно получить с помощью функции id(obj). Теперь две переменные, ссылающиеся на один и тот же объект, будут иметь одинаковый id, то есть id - это адрес памяти объекта, и он уникален в течение жизненного цикла объекта.
charles = {'name': 'Charles L. Dodgson', 'born': 1832} lewis = charles print(lewis is charles) # True print(id(charles), id(lewis)) # (4300473992, 4300473992) lewis['balance'] = 950 print(charles) # {'name': 'Charles L. Dodgson', 'born': 1832, 'balance': 950} alex = {'name': 'Charles L. Dodgson', 'born': 1832, 'balance': 950} print(alex == charles) # True print(alex is not charles) # False
Операторы is и not сравнивают идентичность двух объектов, а функция
Id() возвращает целое число, представляющее идентичность.
Оператор == сравнивает значения объектов, то есть данные, которые они хранят, и именно это нас часто интересует больше всего.
Оператор is не может быть перегружен и, как правило, работает быстрее, чем оператор ==, поскольку его можно перегрузить.
Большинство встроенных типов и объектов Python переопределяют специальный метод __eq__ для поддержки оператора ==.
Мелкие копии делать проще всего, но это может быть не то, что вам нужно.
Неглубокие копии копируют ссылки на копируемый объект, т.е. вы не создаете новые объекты, а просто ссылаетесь на существующие встроенные объекты.
Это экономит память и не вызывает проблем, если все объекты неизменяемы, но если есть изменяемые объекты, это может привести к неприятным сюрпризам.
list_1 = [3, [66, 55, 44], (7, 8, 9)] list_2 = list(list_1)
Это означает, что при создании неглубокой копии списка с помощью конструктора будут ссылаться только на существующие объекты в исходном списке.
list_1.append(100) list_1[1].remove(55) print('list_1:', list_1) # list_1: [3, [66, 44], (7, 8, 9), 100] print('list_2:', list_2) # list_2: [3, [66, 44], (7, 8, 9)] list_2[1] += [33, 22] list_2[2] += (10, 11) print('list_1:', list_1) # list_1: [3, [66, 44, 33, 22], (7, 8, 9), 100] print('list_2:', list_2) # list_2: [3, [66, 44, 33, 22], (7, 8, 9, 10, 11)]
Несколько моментов, которые следует иметь в виду:
Глубокие копии - это дубликаты, которые не разделяют ссылки встроенных объектов, то есть при глубоком копировании списка или любого объекта вы создадите новые ссылки для его встроенных объектов.
В стандартной библиотеке есть модуль, который реализует это, он предлагает две функции copy() и deepcopy(), первая - для поверхностного копирования, а вторая - для глубокого.
import copy class Bus: def __init__(self, passengers=None): if passengers is None: self.passengers = [] else: self.passengers = list(passengers) def pick(self, name): self.passengers.append(name) def drop(self, name): self.passengers.remove(name) bus1 = Bus(['Alice', 'Bill', 'Claire', 'David']) bus2 = copy.copy(bus1) bus3 = copy.deepcopy(bus1) print(id(bus1), id(bus2), id(bus3)) # (4301498296, 4301499416, 4301499752) bus1.drop('Bill') print(bus2.passengers) # ['Alice', 'Claire', 'David'] print(id(bus1.passengers), id(bus2.passengers), id(bus3.passengers)) # (4302658568, 4302658568, 4302657800) print(bus3.passengers) # ['Alice', 'Bill', 'Claire', 'David']
Иногда создание глубокой копии может привести к ошибкам, есть объекты, которые могут иметь циклические ссылки, или объекты могут ссылаться на внешние ресурсы, которые не должны копироваться.
Решением является реализация собственных специальных методов __copy__ и __deepcopy__.
Объекты в Python никогда не уничтожаются явно, как, например, в C#, они собираются в мусор, когда становятся недоступными.
У нас есть оператор, который удаляет ссылки, del, но никогда - объекты.
a = [1, 2] b = a del a print(b) # [1, 2] b = [3] # The original object is now ready to be garbage collected
'сборщик мусора выбросит объект из памяти, если на него нет ссылок.
20.08.2023 18:21
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в 2023-2024 годах? Или это полная лажа?".
20.08.2023 17:46
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
19.08.2023 18:39
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в частности, магию поплавков и гибкость flexbox.
19.08.2023 17:22
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для чтения благодаря своей простоте. Кроме того, мы всегда хотим проверить самые последние возможности в наших проектах!
18.08.2023 20:33
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий их языку и культуре.
14.08.2023 14:49
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип предназначен для представления неделимого значения.