Когда вы используете
self._wr = weakref.ref(self, lambda wr, n = self.name: del_A(n))
обратный вызов будет вызван только тогда, когда self
собирается завершиться.
Причина, по которой обратный вызов не вызывается, заключается в том, что
a = A('a1')
b = B()
a.other = b # This gives a another attribute; it does not switch `a` away from the original `a`
b.other = a
не приводит к финализации a
. Оригинал a
все еще существует.
Обратный вызов будет вызван, если вы измените код на
a = A('a1')
b = B()
a = b
b = a
Когда вы используете
self._wr = weakref.ref(self, del_A(self.name))
тогда ваш обратный вызов None
. del_A(self.name)
это не ссылка на функцию, это сам вызов функции. Таким образом, del_A(self.name)
печатает An A deleted:a1
немедленно (до того, как a1
действительно будет завершен) и возвращается со значением None
, которое становится обратным вызовом по умолчанию для слабой ссылки.