не может слабая ссылка не оценить None, даже если не слабые ссылки указывают на объект? - PullRequest
2 голосов
/ 21 марта 2012

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

Делает ли язык какие-либо другие гарантии относительно слабых ссылок?В частности, предположим, что я создаю слабую ссылку wr, указывающую на некоторый объект.Предположим, что к более позднему времени все неслабые ссылки на этот объект были уничтожены.Гарантируется ли, что в это время wr будет оцениваться как None, или какое-то время он все еще будет оценивать исходный объект?

Помимо языковых гарантий, есть ли какое-нибудь интересное поведение реализации со слабой связью?

Ответы [ 4 ]

1 голос
/ 21 марта 2012

Нет, Python не дает никаких гарантий относительно того, когда объект действительно будет собран, а слабый ответ вернет None. Это может произойти сразу (и это часто происходит в CPython, который использует подсчет ссылок плюс сборщик мусора с циклическими ссылками, но гораздо реже в других реализациях Python, не использующих пересчет). Это также может быть отложено для ряда причины - когда не используется CPython (или не используется версия CPython, в которой не используется пересчет), или когда используется пересчет, но когда ваши объекты участвуют в ссылочном цикле.

1 голос
/ 21 марта 2012

Слабая ссылка либо дает вам действительный объект (из POV Python), либо None.В этот момент объект фактически освобождается (что приводит к тому, что слабая ссылка переходит в None) не определено, за исключением того, что не может быть никаких неслабых ссылок на объект из любых других живых объектов.Поведение подсчета ссылок, которое вы наблюдаете в CPython, не гарантируется.

1 голос
/ 21 марта 2012

Объект со слабой ссылкой будет уничтожен только после включения GC. Поскольку это недетерминировано, не гарантируется, что он будет уничтожен, как только будут удалены все сильные ссылки.

Из docs :

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

Оперативная фраза «свободно уничтожать референта» - это может произойти не сразу.

0 голосов
/ 23 марта 2012

Так как кажется, что все слабые ссылки, выпущенные последовательно, не гарантированы (согласно посту Гвидо).Одна вещь, которую вы могли бы сделать, - это использовать одну слабую ссылку в каждом месте, где в противном случае вы генерировали бы новую слабую ссылку (поскольку единственная ссылка должна выглядеть одинаково для всех, кто ее использует).

Здесь вы потеряли бы хороший механизм обратного вызова для всех различных ссылок на ссылки, но вы могли бы восстановить их, поместив в подклассираж слабый_ref.ref и добавив какую-то схему регистрации.Вам также понадобится какой-то способ найти единственный экземпляр слабого рефери.Либо упакуйте его в экземпляр, на который будет ссылаться, и создайте вспомогательный метод для его получения, либо создайте его (помните о проблемах безопасности потоков, используйте getattr со значением по умолчанию, если вы не хотите блокировать тоже).В качестве альтернативы вы можете сделать синглтон, чтобы найти их (используйте первый метод ...).

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

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

...