Ассоциация
Если в случае агрегации имеется довольно четкое отношение «ИМЕЕТ» (HAS–A) или «СОДЕРЖИТСЯ–В», которое даже отражено в синтаксисе Python:
lst = [1, 2, 3]
if 1 in lst:
...
то в случае ассоциации ссылка на экземпляр другого класса используется без отношения включения одного в другой или принадлежности. О таком отношении между классами говорят как об отношении USE–A («ИСПОЛЬЗУЕТ»). Это достаточно общее отношение зависимости между классами.
В языке Python границы между агрегацией и ассоциацией несколько размыты, так как объекты при агрегации обычно не хранятся в области памяти, выделенной под контейнер (хранятся только ссылки).
Объекты могут также ссылаться друг на друга. В этом случае возникают циклические ссылки, которые при неаккуратном использовании могут привести (в старых версиях Python) к утечкам памяти. В новых версиях Python для циклических ссылок работает сборщик мусора.
Разумеется, при «чистой» агрегации циклических ссылок не возникает.
Например, при представлении дерева ссылки могут идти от родителей к детям и обратно от каждого дочернего узла к родительскому.
Слабые ссылки
Для обеспечения ассоциаций объектов без свойственных ссылкам проблем с возможностью образования циклических ссылок, в Python для сложных структур данных и других видов использования, при которых ссылки не должны мешать удалению объекта, предлагается механизм слабых ссылок. Такая ссылка не учитывается при подсчете ссылок на объект, а значит, объект удаляется с исчезновением последней «сильной» ссылки.
Для работы со слабыми ссылками применяется модуль weakref. Основные принципы его работы станут понятны из следующего примера:
>>> import weakref
>>>
>>> class MyClass(object):
... def __str__(self):
... return "MyClass"
...
>>>
>>> s = MyClass() # создается экземпляр класса
>>> print s
MyClass
>>> s1 = weakref.proxy(s) # создается прокси–объект
>>> print s1 # прокси–объект работает как исходный
MyClass
>>> ss = weakref.ref(s) # создается слабая ссылка на него
>>> print ss() # вызовом ссылки получается исходный объект
MyClass
>>> del s # удаляется единственная сильная ссылка на объект
>>> print ss() # теперь исходного объекта не существует
None
>>> print s1
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ReferenceError: weakly–referenced object no longer exists
К сожалению, поведение прокси–объекта не совсем такое, как у исходного: он не может быть ключом словаря, так как является нехэшируемым.
Больше книг — больше знаний!
Заберите 30% скидку новым пользователям на все книги Литрес с нашим промокодом
ПОЛУЧИТЬ СКИДКУ