2015-10-06 19 views
6

with ifadesinde oluşturulan değişkenlerin kapsamı with blokunun dışındadır (bkz. Variable defined with with-statement available outside of with-block?). Aşağıdaki kodu çalıştırdığınızda Ama:Neden bir blokun sonunda __del__ denir?

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 

çıkış Foo.__del__ (yukarıda # line 1 at) foo yazdırmadan önce çağrılır gösterir:

__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 

Sorum şu, neden ise Foo.__del__, burada adlandırılan olduğunu with bildirimi yeni bir yürütme kapsamı oluşturmuyor mu? bağlantının __del__ yöntem ikinci with blokta denir eğer my_curs1.connection sonra (yukarıda # line 2 bakınız) hala açık neden

Ayrıca, ben anlamıyorum.

+1

Olası kopyası [MySQLdb.Connection nesnesiyle birlikte kullanabilir miyim?] (Http://stackoverflow.com/questions/11751703/can-i-use-with-statement-with-mysqldb-connection-object) – tzaman

+2

Chengcheng, ikinci sorunun cevabını görmek için @ tzaman'ın bağlantısını tıklayın ve bu bölümü sorunuzdan kaldırın. Tek bir soruyu bir soruya tutturmak, StackOverflow'un düzenli tutulmasına yardımcı olur ve insanların cevapları daha hızlı bulmasını sağlar. Teşekkür ederim! – CodeMouse92

+1

@tzaman Bu soru 3 yaşında ve cevabı yanlış. – Air

cevap

2

foo'un Foo türünde bir nesne olmadığını unutmayın. Bir Foo oluşturuyorsunuz ve onu saklamak gerekiyor çünkü __exit__ numaralı telefonu aramak için gereken durum bilgilerini içerebilir. Ama bir kez bittiğinde, nesne gereksizdir ve Python onu atmak için özgürdür.

Başka bir deyişle, bu:

with Foo() as foo: 
    print ('Hello World!') 

bu aynı mı:

_bar = Foo() 
foo = _bar.__enter__() 
print ('Hello World!') 
_bar.__exit__() 
del _bar # This will call __del__ because _bar is the only reference 

Eğer foowith bloğun foo bir başvuru olsaydı ne olurdu bekliyoruz davranışı. Örneğin ...

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 

Baskılar

__int__() called. 
__enter__() called. 
with block begin??? 
with block end??? 
__exit__() called. 
foo: returned_test_str 
__del__() called. 

Ben Connection.__exit__ ancak açık olan imleçlerini bırakacaktı neden hiçbir fikrim yok.

+0

) kapanışla (self .__ conn.cursor()) cur olarak: "" arayacak(), ancak __exit __() ve __enter __(). Ancak with-deyimi __exit __() ve __enter __() işlevlerini çağırır, ancak close() işlevini çağırmaz. Lütfen http://stackoverflow.com/questions/5669878/when-to-close-cursors-using-mysqldb – BAE

+0

adresine bakın. Neden sadece print cümlesi (postumdaki satır 1) için __del __() çağrıldığını merak ediyorum. Program çıkışında __del __() çağrılırsa bana mantıklı gelirim. – BAE

+0

'__del__' çağrılıyor çünkü' with' bloğu tarafından oluşturulan geçici nesneye daha fazla gönderme yapılmıyor. Unutma, 'foo' yaptığınız Foo() değil. – QuestionC

İlgili konular