Я наблюдаю странное поведение с Python 2.7.12 и Python 3.5.2:
import sys
class Foo:
def __init__(self):
self.b = self.bar
def bar(self):
pass
f = Foo()
print(sys.getrefcount(f) - 1) # subtract the extra reference created by
# passing a reference to sys.getrefcount.
Когда я запускаю код в python, я получаю 2, что означает, что есть две ссылки на объект Foo. Единственное решение — удалить self.b = self.bar
. Кажется, создается ссылка на цикл.
Кто-нибудь может объяснить поведение?
ОБНОВЛЕНИЕ: вот результаты запуска:
class Foo:
def __init__(self):
self.b = self.bar
def bar(self):
pass
def __del__(self):
print "deleted"
def test_function():
f = Foo()
print f
if __name__ == "__main__":
for i in xrange(5):
test_function()
print "finished"
python ./test.py
<__main__.Foo instance at 0x104797e60>
<__main__.Foo instance at 0x104797ef0>
<__main__.Foo instance at 0x104797f38>
<__main__.Foo instance at 0x104797f80>
<__main__.Foo instance at 0x104797fc8>
finished
Как видите, на каждой итерации python создает новый экземпляр класса Foo, но никогда их не выпускает!
ОБНОВЛЕНИЕ 2 И ПРИЧИНА
Объекты, имеющие методы del() и являющиеся частью ссылочного цикла, делают весь ссылочный цикл недоступным для сбора, включая объекты, не обязательно находящиеся в цикле, но доступные только из него. https://docs.python.org/2/library/gc.html#gc.garbage
Экземпляр класса Foo имеет как метод __del__
, так и связанный метод self.b = self.bar
, что означает, что он определенно является частью эталонного цикла. Таким образом, согласно документации py, экземпляр не подлежит сбору!
__del__
. Он звонитos.fdclose
. Это мешает сборке мусора? Да, ваше решение решает проблему :) 19.06.2018