Python - деструктор гарантии называется (сразу) [дубликат]

Это все в «волшебном» синтаксисе вызова метода:

object.property();

Когда вы получаете свойство из объекта и вызываете его за один раз, объект будет контекстом для метода , Если вы вызываете тот же метод, но в отдельных шагах, контекст представляет собой глобальную область (окно):

var f = object.property;
f();

Когда вы получаете ссылку на метод, он больше не привязан к объекту, это просто ссылка на простую функцию. То же самое происходит, когда вы получаете ссылку на использование в качестве обратного вызова:

this.saveNextLevelData(this.setAll);

Здесь вы привязываете контекст к функции:

this.saveNextLevelData(this.setAll.bind(this));

Если вы используете jQuery вы должны использовать метод $.proxy, а bind не поддерживается во всех браузерах:

this.saveNextLevelData($.proxy(this.setAll, this));
59
задан wim 4 December 2015 в 16:51
поделиться

4 ответа

Способы закрытия ресурсов - это администраторы контекста, также как и оператор with:

class Foo(object):

  def __init__(self):
    self.bar = None

  def __enter__(self):
    if self.bar != 'open':
      print 'opening the bar'
      self.bar = 'open'
    return self # this is bound to the `as` part

  def close(self):
    if self.bar != 'closed':
      print 'closing the bar'
      self.bar = 'close'

  def __exit__(self, *err):
    self.close()

if __name__ == '__main__':
  with Foo() as foo:
    print foo, foo.bar

output:

opening the bar
<__main__.Foo object at 0x17079d0> open
closing the bar

2) Объекты Python удаляются когда их счетчик ссылок равен 0. В вашем примере del foo удаляет последнюю ссылку, поэтому __del__ вызывается мгновенно. GC не участвует в этом.

class Foo(object):

    def __del__(self):
        print "deling", self

if __name__ == '__main__':
    import gc
    gc.disable() # no gc
    f = Foo()
    print "before"
    del f # f gets deleted right away
    print "after"

output:

before
deling <__main__.Foo object at 0xc49690>
after

gc не имеет ничего общего с удалением вашего и большинства других объектов. Он должен очищаться, когда простой подсчет ссылок не работает из-за самореференций или круговых ссылок:

class Foo(object):
    def __init__(self, other=None):
        # make a circular reference
        self.link = other
        if other is not None:
            other.link = self

    def __del__(self):
        print "deling", self

if __name__ == '__main__':
    import gc
    gc.disable()   
    f = Foo(Foo())
    print "before"
    del f # nothing gets deleted here
    print "after"
    gc.collect()
    print gc.garbage # The GC knows the two Foos are garbage, but won't delete
                     # them because they have a __del__ method
    print "after gc"
    # break up the cycle and delete the reference from gc.garbage
    del gc.garbage[0].link, gc.garbage[:]
    print "done"

output:

before
after
[<__main__.Foo object at 0x22ed8d0>, <__main__.Foo object at 0x22ed950>]
after gc
deling <__main__.Foo object at 0x22ed950>
deling <__main__.Foo object at 0x22ed8d0>
done

3) Позволяет см.:

class Foo(object):
    def __init__(self):

        raise Exception

    def __del__(self):
        print "deling", self

if __name__ == '__main__':
    f = Foo()

дает:

Traceback (most recent call last):
  File "asd.py", line 10, in <module>
    f = Foo()
  File "asd.py", line 4, in __init__
    raise Exception
Exception
deling <__main__.Foo object at 0xa3a910>

Объекты создаются с помощью __new__, а затем передаются в __init__ как self. После исключения из __init__ у объекта обычно не будет имени (т. Е. Часть f = не будет запущена), поэтому их количество ссылок равно 0. Это означает, что объект удаляется нормально и вызывается __del__.

67
ответ дан Jochen Ritzel 21 August 2018 в 02:14
поделиться
  • 1
    & GT; Способы закрытия ресурсов - это менеджеры контекста, также как и оператор with. Отличный наконечник. Не знал, что with может использоваться для того, чтобы содержать область для любого объекта таким образом. – Lelouch Lamperouge 15 October 2013 в 00:32

В общем, чтобы убедиться, что что-то происходит независимо от того, что вы используете

from exceptions import NameError

try:
    f = open(x)
except ErrorType as e:
    pass # handle the error
finally:
    try:
        f.close()
    except NameError: pass

finally, будут выполняться независимо от того, есть ли ошибка в блоке try и есть ли или нет ошибки в обработке ошибок, которая имеет место в блоках except. Если вы не обрабатываете возбужденное исключение, оно все равно будет поднято после того, как будет отменен блок finally.

Общий способ убедиться, что файл закрыт, - это использовать «менеджер контекста» ".

http://docs.python.org/reference/datamodel.html#context-managers

with open(x) as f:
    # do stuff

Это автоматически закроет f.

Для вашего вопроса №2, bar немедленно закрывается, когда счетчик ссылок достигает нуля, поэтому del foo, если других ссылок нет.

Объекты НЕ созданы __init__, они созданы __new__.

http://docs.python.org/reference/datamodel.html#object.new

Когда вы делаете foo = Foo(), на самом деле происходит две вещи: сначала создается новый объект __new__, затем он инициализируется __init__. Таким образом, вы не можете называть del foo до того, как эти шаги будут выполнены. Однако, если в __init__ есть ошибка, __del__ все равно будет вызываться, потому что объект фактически был создан в __new__.

Редактировать: Исправлено, когда удаление происходит, если счетчик ссылок уменьшается до равен нулю.

8
ответ дан agf 21 August 2018 в 02:14
поделиться
  • 1
    Ваш пример try..except..finally нарушен: если open() выбрасывает исключение, f будет отменено, и, наконец, это не сработает. – Duncan 21 July 2011 в 08:39
  • 2
    Спасибо, исправлено. Тем не менее, он по-прежнему будет гарантировать, что f был закрыт, поскольку ошибка произошла только в том случае, когда она никогда не открывалась. – agf 21 July 2011 в 08:45
  • 3
    @afg вы ошибаетесь в отношении gc и когда объекты удаляются, см. мой ответ. – Jochen Ritzel 21 July 2011 в 09:15
  • 4
    @ Йохен-Ритцел. ваши примеры очень показательны. – agf 21 July 2011 в 09:48
  1. Добавьте обработчик выхода , который закрывает все столбцы.
  2. __del__() вызывается, когда количество ссылок на объект достигает 0, пока виртуальная машина все еще остается Бег. Это может быть вызвано GC.
  3. Если __init__() вызывает исключение, предполагается, что объект является неполным, а __del__() не будет вызываться.
2
ответ дан Ignacio Vazquez-Abrams 21 August 2018 в 02:14
поделиться
  • 1
    В качестве побочного примечания: os._exit позволяет завершить обход всех функций закрытия. – cwallenpoole 21 July 2011 в 08:21

Возможно, вы ищете менеджер контекста ?

>>> class Foo(object):
...   def __init__(self):
...     self.bar = None
...   def __enter__(self):
...     if self.bar != 'open':
...       print 'opening the bar'
...       self.bar = 'open'
...   def __exit__(self, type_, value, traceback):
...     if self.bar != 'closed':
...       print 'closing the bar', type_, value, traceback
...       self.bar = 'close'
... 
>>> 
>>> with Foo() as f:
...     # oh no something crashes the program
...     sys.exit(0)
... 
opening the bar
closing the bar <type 'exceptions.SystemExit'> 0 <traceback object at 0xb7720cfc>
5
ответ дан John La Rooy 21 August 2018 в 02:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: