2013-01-06 71 views
8

如何使用Contextmanager作爲實例變量?例如。 讓我們假設我有一些Connection類,它必須在銷燬時關閉。如果我將它作爲一個ContextManager實現,我可以做到。如何使用contextmanagers作爲實例變量

with Connection() as c: 
    c.write('FOO') 
    c.ask('BAR?') 

它會在銷燬時自動關閉。但是如果我想在另一個課程的__init__中使用它,例如像下面的例子一樣?

class Device(object): 
    def __init__(self): 
     self.connection = Connection() # Must be closed on destruction. 

我不希望它在構造函數退出時被關閉,它應該在對象被銷燬時死掉。我可以使用__del__,但這有缺點。習慣了C++中的RAII,它讓我感到困惑。

那麼在這種情況下最好的方法是什麼?

+2

對象銷燬時間永遠不是適合任何事情的時候,特別是對於資源管理而言。忘記有垃圾收集這樣的事情,並假設所有對象都無限期地活着。 – delnan

回答

6

您應該在您的Device.close()方法中調用self.connection.close,然後安排在程序中正確調用該方法,或者使用上下文管理器。

__del__永遠不值得。

1
from contextlib import contextmanager 

@contextmanager 
def connection(): 
    conn = Conn() 
    try: 
     yield conn 
    finally: 
     conn.close() 

class Conn(object): 
    def close(self): 
     print('Closing') 

class Device(object): 
    def __init__(self, conn): 
     self.conn = Conn() 

with connection() as conn: 
    d = Device(conn)