Python del на классах

Предположим, у нас есть класс на питоне:

class A(object):
    def __del__(self):
        print "Del!"

__del__ вызывается при удалении/сборке мусора любого экземпляра A.

Можно ли сделать то же самое для класса? Я хотел бы, чтобы какой-то метод вызывался, когда сам класс собирает мусор, что, как я полагаю, выполняется при выходе из скрипта.

Заранее спасибо за любые указатели!


Редактировать: Как я и ожидал, все пытаются отговорить меня от использования этой техники (я, наверное, сам сделал бы такой комментарий:)), хотя вопрос остается в силе: возможно ли это?

Я хочу следующее: у меня есть класс со статическим членом, который нужно очистить.

class A(object):
    class Meta(type):
        def __new__(mcs, name, bases, attrs):
            attrs['conn'] = sqlite3.connect( DB_FILE )
            return type.__new__(mcs, name, bases, attrs)

    __metaclass__ = Meta

Я хотел бы, чтобы A.conn.close() вызывался, но непосредственно перед закрытием программы, т.е. когда я знаю, что больше экземпляров A не будет создано. Я знаю, что могу сделать это с atexit, но это выглядит очень некрасиво.


person pajton    schedule 09.04.2011    source источник
comment
Использование __del__ уже подозрительно. Это может сделать объекты неспособными к сборке мусора (при наличии цикла сборщик мусора не знает, в каком порядке они должны вызываться, поскольку, вероятно, есть некоторые зависимости), и поскольку это недетерминировано, очистку лучше помещать в контекст управляющий делами. Как вы думаете, зачем вам это нужно?   -  person    schedule 10.04.2011
comment
Вы можете создать фабричный класс, который имеет метод __call__ для создания нового экземпляра желаемого класса и метод __del__, который делает то, что вы хотите.   -  person Oleh Prypin    schedule 10.04.2011
comment
И вообще, я не могу придумать ничего полезного, что можно сделать из этого.   -  person Oleh Prypin    schedule 10.04.2011
comment
Никогда не полагайтесь на сбор мусора для определенного набора действий. Время выполнения не обязано что-либо собирать, даже при завершении программы. если вам нужна очистка, используйте контекстный менеджер.   -  person SingleNegationElimination    schedule 10.04.2011
comment
В среде со сборкой мусора деструкторы — это плохо. Избегай это. Или, скорее, задайте вопрос о проблеме, которую вы решаете, а не о мелких технических деталях. Вероятно, это принесло бы реальные ответы.   -  person 9000    schedule 10.04.2011
comment
Спасибо за все комментарии, я предоставил больше информации в своем вопросе.   -  person pajton    schedule 10.04.2011
comment
@pajton - ваша дополнительная информация подтверждает, что это неправильный подход. @TokenMacGuy абсолютно прав в том, что очистка может никогда не произойти.   -  person detly    schedule 10.04.2011
comment
Я знаю, что это не очень элегантный подход. Что лучше вы предлагаете?   -  person pajton    schedule 10.04.2011
comment
@pajton - вы можете использовать одну из нескольких библиотек ORM, которые сделают все это за вас за кулисами. На ум приходят SQLObject или SQLAlchemy.   -  person detly    schedule 10.04.2011
comment
То, что я пишу, должно быть простым ORM :-). Знаете ли вы, как SQLObject или SQLAlchemy обрабатывают соединения с БД? (т.е. они открыты все время и когда они закрыты)   -  person pajton    schedule 10.04.2011
comment
Не могли бы вы использовать atexit в Meta::__new__ и скрыть его уродство?   -  person martineau    schedule 10.04.2011
comment
Я мог бы (как я уже упоминал в своем вопросе:)) и даже делаю это сейчас. Но я ищу более чистое решение, если это возможно.   -  person pajton    schedule 11.04.2011
comment
@pajton - а, ладно :) Я бы посмотрел исходный код SQLObject.   -  person detly    schedule 11.04.2011


Ответы (1)


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

Я мог вызвать его, используя реализацию Pypy Python, но не используя cpython — либо 2.6, либо 3.2. И даже для того, чтобы вызвать это, мне пришлось вручную вызвать сборщик мусора — среда Python при выходе из программы, как известно, полна несоответствий, и вероятность того, что метод __del__ будет вызван, в то время как будет существовать достаточно внутренней информации о классе, чтобы позволить sae выключить было бы очень тонко.

Вот мой сеанс Pypy, в котором я вызвал вызов класса __del__

 ~]$ pypy                                                                                       
Python 2.5.2 (78826, Nov 29 2010, 00:18:05)                                                                       
[PyPy 1.4.0] on linux2                                                                                            
Type "help", "copyright", "credits" or "license" for more information.                                            
And now for something completely different: ``sorry, I'll teach the cactus how                                    
to swim later''                                                                                                   
>>>> import gc
>>>> class Meta(type):         
....    def __del__(cls):                          
....       print ("Arghh!!")                                              
....                                                                      
>>>> class A(object):                                                                     
....   __metaclass__ = Meta                                                                                     
....                                                                                                                                                                                                                
>>>> del A                                                                                                        
>>>> gc.collect()                                                                                                 
Arghh!!                                                                                                           
0                                                                                                                 
>>>>
person jsbueno    schedule 10.04.2011
comment
And now for something completely different: "sorry, I'll teach the cactus how to swim later" Это сделало мой день лучше. Спасибо. - person FunkySayu; 09.10.2015