Объекты являются основной конструкцией любого языка ООП, и каждый язык определяет свой собственный синтаксис для их создания, обновления и уничтожения. В 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.03.2023 14:01
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а также новые инструменты веб-скраппинга с открытым исходным кодом для их обхода.
20.03.2023 12:24
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие действия:
20.03.2023 11:15
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц. HTML обеспечивает структуру страницы CSS (визуальное и звуковое) оформление для различных устройств. Наряду с графикой и сценариями HTML и CSS являются...
20.03.2023 08:46
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
19.03.2023 13:43
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем запускать наши php-файлы через localhost на наших компьютерах. Мне с трудом удалось установить его и я решил поделиться этой статьей, чтобы помочь тем,...
19.03.2023 13:03
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после поставщика контекста. Это позволит избежать ненужных повторных рендеров.