Освобождение статической переменной Python

Когда нижеприведенный статический класс python собирает мусор? Я ожидал увидеть сообщение от деструктора статической переменной foo.

class Foo(object):
    def __init__(self):
        print "Foo init running"

    def __del__(self):
        print "Destructor Foo"

class Bar(object):
    foo = Foo()
    def __init__(self):
        print "Bar init running"

    def __del__(self):
        print "Destructor Bar"

bar_obj = Bar()

Вывод (Python 2.7):

Foo init running
Bar init running
Destructor Bar

Я ожидал:

Foo init running
Bar init running
Destructor Foo
Destructor Bar

person A.P.    schedule 09.10.2015    source источник
comment
Для меня не дубликат. Другой вопрос касается circular references.   -  person luoluo    schedule 09.10.2015
comment
stackoverflow.com/questions/14628486/   -  person Cong Ma    schedule 09.10.2015
comment
А что такое статическая переменная Python? Существует ли это понятие?   -  person Cong Ma    schedule 09.10.2015
comment
Он работает в Python 3.4   -  person strubbly    schedule 12.10.2015


Ответы (1)


Таким образом, мы ожидаем, что ссылка на объект foo будет удалена при удалении класса Bar. И это обычно то, что происходит. Если вы попытаетесь

class Foo(object):
    def __init__(self):
        print("Foo init running")

    def __del__(self):
        print("Destructor Foo")

class Bar(object):
    foo = Foo()
    def __init__(self):
        print("Bar init running")

    def __del__(self):
        print("Destructor Bar")


def f():
    bar_obj = Bar()

f()
del Bar

я получил

Foo init running
Bar init running
Destructor Bar
Destructor Foo

и вы можете видеть, что оба деструктора вызываются как в Python 2.7, так и в Python 3.4. Однако в Python 2.7 Bar не уничтожается должным образом во время закрытия программы. Как говорят документы:

Не гарантируется, что методы del() будут вызываться для объектов, которые все еще существуют, когда интерпретатор завершает работу.

Почему Bar не уничтожается при выходе из интерпретатора?

Кажется вероятным, что класс в Python 2.7 не уничтожается из-за циклических ссылок (см. ниже). В Python 3.4 (после PEP 442) объекты с циклическими ссылками надежно уничтожаются (даже если у них есть __del__ методов), и это может объяснить изменение.

Однако это не полностью объясняет разницу, поскольку, хотя класс находится в ссылочном цикле, сам класс не имеет деструктора.

Кажется, что в Python 2 объекты с циклическими ссылками не уничтожаются надежно при выходе из интерпретатора, тогда как в Python 3.4 они есть. Я даю дополнительную информацию здесь.

Изменить (подробнее о циклических ссылках):

Классы содержат циклические ссылки на самих себя, сначала через свой словарь:

MyClass.__dict__['__dict__'].__objclass__ == MyClass

и, во-вторых, через их данные MRO:

MyClass in MyClass.__mro__
person strubbly    schedule 12.10.2015
comment
Это не объясняет, почему он не удален. - person luoluo; 12.10.2015
comment
Это функция Python 2.7, но я не совсем понимаю обоснование дизайна. - person strubbly; 12.10.2015
comment
Хм - еще раз подумал, и я придумал правдоподобное объяснение - person strubbly; 12.10.2015
comment
Можете ли вы объяснить, где находится циклическая ссылка? Пожалуйста, уточните немного ваш последний абзац. Я не совсем понимаю это. - person A.P.; 14.10.2015
comment
@А.П. Ну, я не уверен - я получил его из здесь. Но я изучаю это. Конечно, все классы имеют ссылку на свой метакласс, а некоторые метаклассы имеют ссылки на классы, но не уверен, что все так? - person strubbly; 14.10.2015
comment
Экземпляр Bar (bar_obj) уничтожен (я вижу выполнение del). Экземпляр Foo (foo), который является частью класса Bar в качестве статической переменной, не уничтожается (я не вижу del). - person A.P.; 21.10.2015
comment
@А.П. У меня работает на 2.7.10. Вы удаляете bar_obj? В моем коде он удаляется, когда заканчивается выполнение f. Я вставлю точный код в свой ответ, и вы сможете протестировать... - person strubbly; 21.10.2015