为什么 __del__ 在 with 块的末尾被调用?
Why is __del__ called at the end of a with block?
在with
语句中创建的变量范围在with
块之外(参考:Variable defined with with-statement available outside of with-block?)。但是当我运行下面的代码:
class Foo:
def __init__(self):
print "__int__() called."
def __del__(self):
print "__del__() called."
def __enter__(self):
print "__enter__() called."
return "returned_test_str"
def __exit__(self, exc, value, tb):
print "__exit__() called."
def close(self):
print "close() called."
def test(self):
print "test() called."
if __name__ == "__main__":
with Foo() as foo:
print "with block begin???"
print "with block end???"
print "foo:", foo # line 1
print "-------- Testing MySQLdb -----------------------"
with MySQLdb.Connect(host="xxxx", port=0, user="xxx", passwd="xxx", db="test") as my_curs2:
print "(1)my_curs2:", my_curs2
print "(1)my_curs2.connection:", my_curs2.connection
print "(2)my_curs2.connection:", my_curs2.connection
print "(2)my_curs2.connection.open:", my_curs2.connection.open # line 2
输出显示 Foo.__del__
在打印 foo 之前被调用(在 # line 1
上面):
__int__() called.
__enter__() called.
with block begin???
with block end???
__exit__() called.
__del__() called.
foo: returned_test_str
-------- Testing MySQLdb -----------------------
(1)my_curs2: <MySQLdb.cursors.Cursor object at 0x7f16dc95b290>
(1)my_curs2.connection: <_mysql.connection open to 'xxx' at 2609870>
(2)my_curs2.connection: <_mysql.connection open to 'xxx' at 2609870>
(2)my_curs2.connection.open: 1
我的问题是,如果 with
语句没有创建新的执行范围,为什么会在这里调用 Foo.__del__
?
另外,如果在第二个with
块中调用连接的__del__
方法,我不明白为什么my_curs1.connection
之后仍然打开(参见# line 2
以上)。
请务必注意 foo
不是 Foo
类型的对象。您确实创建了一个 Foo
并需要保留它,因为它可能包含调用 __exit__
所需的状态信息。但是一旦完成,该对象就不再需要了,Python 可以随意丢弃它。
换句话说,这个:
with Foo() as foo:
print ('Hello World!')
与此相同:
_bar = Foo()
foo = _bar.__enter__()
print ('Hello World!')
_bar.__exit__()
del _bar # This will call __del__ because _bar is the only reference
如果 foo
是对 with
块的 foo 的引用,就会发生您期望的行为。例如...
class Foo:
def __init__(self):
print ("__int__() called.")
def __del__(self):
print ("__del__() called.")
def __enter__(self):
print ("__enter__() called.")
return self # foo now stores the Foo() object
def __str__(self):
return 'returned_test_str'
def __exit__(self, exc, value, tb):
print ("__exit__() called.")
def close(self):
print ("close() called.")
def test(self):
print ("test() called.")
if __name__ == "__main__":
with Foo() as foo:
print ("with block begin???")
print ("with block end???")
print ("foo:", foo) # line 1
版画
__int__() called.
__enter__() called.
with block begin???
with block end???
__exit__() called.
foo: returned_test_str
__del__() called.
我不知道为什么 Connection.__exit__
会打开它的游标。
在with
语句中创建的变量范围在with
块之外(参考:Variable defined with with-statement available outside of with-block?)。但是当我运行下面的代码:
class Foo:
def __init__(self):
print "__int__() called."
def __del__(self):
print "__del__() called."
def __enter__(self):
print "__enter__() called."
return "returned_test_str"
def __exit__(self, exc, value, tb):
print "__exit__() called."
def close(self):
print "close() called."
def test(self):
print "test() called."
if __name__ == "__main__":
with Foo() as foo:
print "with block begin???"
print "with block end???"
print "foo:", foo # line 1
print "-------- Testing MySQLdb -----------------------"
with MySQLdb.Connect(host="xxxx", port=0, user="xxx", passwd="xxx", db="test") as my_curs2:
print "(1)my_curs2:", my_curs2
print "(1)my_curs2.connection:", my_curs2.connection
print "(2)my_curs2.connection:", my_curs2.connection
print "(2)my_curs2.connection.open:", my_curs2.connection.open # line 2
输出显示 Foo.__del__
在打印 foo 之前被调用(在 # line 1
上面):
__int__() called.
__enter__() called.
with block begin???
with block end???
__exit__() called.
__del__() called.
foo: returned_test_str
-------- Testing MySQLdb -----------------------
(1)my_curs2: <MySQLdb.cursors.Cursor object at 0x7f16dc95b290>
(1)my_curs2.connection: <_mysql.connection open to 'xxx' at 2609870>
(2)my_curs2.connection: <_mysql.connection open to 'xxx' at 2609870>
(2)my_curs2.connection.open: 1
我的问题是,如果 with
语句没有创建新的执行范围,为什么会在这里调用 Foo.__del__
?
另外,如果在第二个with
块中调用连接的__del__
方法,我不明白为什么my_curs1.connection
之后仍然打开(参见# line 2
以上)。
请务必注意 foo
不是 Foo
类型的对象。您确实创建了一个 Foo
并需要保留它,因为它可能包含调用 __exit__
所需的状态信息。但是一旦完成,该对象就不再需要了,Python 可以随意丢弃它。
换句话说,这个:
with Foo() as foo:
print ('Hello World!')
与此相同:
_bar = Foo()
foo = _bar.__enter__()
print ('Hello World!')
_bar.__exit__()
del _bar # This will call __del__ because _bar is the only reference
如果 foo
是对 with
块的 foo 的引用,就会发生您期望的行为。例如...
class Foo:
def __init__(self):
print ("__int__() called.")
def __del__(self):
print ("__del__() called.")
def __enter__(self):
print ("__enter__() called.")
return self # foo now stores the Foo() object
def __str__(self):
return 'returned_test_str'
def __exit__(self, exc, value, tb):
print ("__exit__() called.")
def close(self):
print ("close() called.")
def test(self):
print ("test() called.")
if __name__ == "__main__":
with Foo() as foo:
print ("with block begin???")
print ("with block end???")
print ("foo:", foo) # line 1
版画
__int__() called.
__enter__() called.
with block begin???
with block end???
__exit__() called.
foo: returned_test_str
__del__() called.
我不知道为什么 Connection.__exit__
会打开它的游标。