Это все в «волшебном» синтаксисе вызова метода:
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));
Способы закрытия ресурсов - это администраторы контекста, также как и оператор 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__
.
В общем, чтобы убедиться, что что-то происходит независимо от того, что вы используете
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__
.
Редактировать: Исправлено, когда удаление происходит, если счетчик ссылок уменьшается до равен нулю.
try..except..finally
нарушен: если open()
выбрасывает исключение, f
будет отменено, и, наконец, это не сработает.
– Duncan
21 July 2011 в 08:39
f
был закрыт, поскольку ошибка произошла только в том случае, когда она никогда не открывалась.
– agf
21 July 2011 в 08:45
__del__()
вызывается, когда количество ссылок на объект достигает 0, пока виртуальная машина все еще остается Бег. Это может быть вызвано GC. __init__()
вызывает исключение, предполагается, что объект является неполным, а __del__()
не будет вызываться. Возможно, вы ищете менеджер контекста ?
>>> 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>
with
может использоваться для того, чтобы содержать область для любого объекта таким образом. – Lelouch Lamperouge 15 October 2013 в 00:32