Вызов функции деструктора в середине программы - PullRequest
0 голосов
/ 22 января 2020

У меня есть один запрос относительно уничтожения объекта и вызова деструктора в середине программы.

Пример:

class ABC: 

    # Initializing 
    def __init__(self): 
        print('Constructor Called') 

    # Destructor 
    def __del__(self): 
        print('Destructor called')

obj = ABC() 
del obj 
# I want destructor to be called here.
# and then print below statement
print("obj deleted") 

Но вместо этого деструктор вызывается в конце программы.

Любая помощь dev?

Ответы [ 2 ]

2 голосов
/ 22 января 2020

Подробно в документации по __del__() ( здесь ):

Примечание del x напрямую не вызывает x.__del__() - первое уменьшает счетчик ссылок для x на единицу, и последний вызывается только тогда, когда счетчик ссылок x достигает нуля.

Если вы пытаетесь «деконструировать» объект Python (и обратите внимание, как я сказано в кавычках), я бы вместо этого рекомендовал использовать __exit__() с оператором with (документы здесь ).

Чтобы использовать оператор with, вы определяете класс с помощью следующих методов:

def __enter__(self)
def __exit__(self, exc_type, exc_value, traceback)

Простым примером будет следующий:

class Bar:
    def __init__(self, *args):
        self.stack = list(args)

    def __enter__(self):
        # Example computation here.
        filtered = filter(lambda x: isinstance(x, str), self.stack)
        return list(filtered)

    def __exit__(self, exc_type, exc_value, traceback):
        del self.stack

# Once you leave the 'with' statement, this Bar() object will be deleted for good. 
with Bar("Hello", "World!", 1, 2) as stack:
    print(stack)

Хотя, честно говоря «деконструкция» объекта в Python почти никогда не требуется, и в большинстве случаев вам следует программировать с намерением избежать попыток выполнить работу сборщика мусора . Использование del - это одно, а попытка «деконструировать» объект - это другое.

1 голос
/ 22 января 2020

Метод __del__ вызывается, когда счетчик ссылок объекта достигает 0 или когда он перебирается сборщиком мусора в случае циклической ссылки. Например, следующее:

class Foo:
    def __del__(self):
        print('Foo has been deleted!')

foo = Foo()
del foo

будет правильно вызывать метод __del__ и печатает Foo has been deleted!, поскольку объект, назначенный foo, был указан только один раз. Теперь давайте рассмотрим следующий пример:

class Foo:
    def __del__(self):
        print('Foo has been deleted!')

foo = Foo()
foo.self = foo
del foo

Метод __del__ не будет вызван, потому что foo.self держит себя в заложниках. Он будет удален только при прохождении сборщиком мусора. Например:

from gc import collect

class Foo:
    def __del__(self):
        print('Foo has been deleted!')

foo = Foo()
foo.self = foo
del foo

collect()

Будет вызван метод __del__, потому что мы сказали сборщику пересечь ожидающие объекты. Не рекомендуется, но вы можете указать Python обойти всю очередь, установив пороговые значения 1. Например:

from gc import set_threshold

set_threshold(1, 1, 1)

class Foo:
    def __del__(self):
        print('Foo has been deleted!')

foo = Foo()
foo.self = foo
del foo

Таким образом, каждый раз, когда создается один объект, сборщик будет запускать его. Но опять же, не рекомендуется, так как это может быть дорогостоящим и повлиять на производительность вашего кода.

...