2014-06-15 7 views
3

에 자식 상황의 관리를 위임 때문에이의 우리가 그것의 고유의 권리로 상황에 맞는 관리자 역할을하는 클래스 'A'를 가지고 있다고 가정 해 봅시다 부모

def __enter__() 
def __exit__() 

인터페이스를 구현하는 방법. 클라이언트 코드가 with 문을 사용하여 직접 'A'객체를 만드는 것은 유효합니다.

이제 'A'개체를 사용하는 다른 기능을 캡슐화하는 또 다른 클래스 'B'가 있습니다.

'B'를 컨텍스트 관리자로 사용하려면 'A'인스턴스를 관리하는 올바른 방법은 무엇입니까?

__enter__와 'B'에 __exit__의 구현은 __enter__ 전화 그것에 (각각) __exit__는 A-객체 인스턴스의할까요? 아니면 더 좋은 방법이 있습니까?

고려 (이 마음에 와서 바로 최초의 비 추상적 인 예입니다, 이것이 내가 내 응용 프로그램에서 사용하고 있지 무엇 이다) 구체적인 예를 제공하기 위해 두 개의 클래스

  • DatabaseConnection
  • DatabaseConnectionPool

따라서 그것은 DatabaseConnection, 그 자체에 하나의 DatabaseConnection를 사용하는 것이 유효의 상황에 관리자 인터페이스를 구현합니다.

DatabaseConnectionPool은 다른 비트 및 봅뿐만 아니라 여러 개의 DatabaseConnections을 사용합니다. 내가했다 몇 가지 테스트 코드를 작성했습니다 :

이 업데이트 (그것을 수행 할 수 있습니다 어떤 다른 사람과 함께) 설정하고에 눈물 다운의 DatabaseConnection 인스턴스를해야한다 ("와"예) DatabaseConnectionPool 사용 다음과 같은 출력 줄 것이라고 기대 :

 
Enter invoked on Outer 
Enter invoked on Inner 
Within outer context... 
do_foo invoked! 
Still using outer... 
Exit invoked on inner 
Exit invoked on outer 
Done using outer 

을하지만 난 다음 가지고 :

 
Enter invoked on Outer 
Enter invoked on Inner 
Exit invoked on inner 
Within outer context... 
do_foo invoked! 
Still using outer... 
Exit invoked on outer 
Done using outer 

코드 :


class Inner(object): 
    def __enter__(self): 
    print "Enter invoked on Inner" 
    return self 

    def __exit__(self, typ, val, tb): 
    print "Exit invoked on inner" 

    def do_foo(self): 
    print "do_foo invoked!" 

class Outer(object): 
    def __init__(self): 
    self._inner = Inner() 

    def __enter__(self): 
    print "Enter invoked on Outer" 

    with self._inner as ctx: 
     return self 

    def __exit__(self, typ, val, tb): 
    print "Exit invoked on outer" 

with Outer() as outer: 
    print "Within outer context..." 
    outer._inner.do_foo() 
    print "Still using outer..." 

print "Done using outer" 

이 작품을 만드는 방법에 대한 아이디어가 있으십니까?

+0

내가이 upvoted했습니다, 그것은하던 재미있는 질문. –

답변

0

정말 디자인 문제이며 판단을 요구합니다. 다음을 제안 할 것입니다 :

풀 클래스 인스턴스는 필요에 따라 프로그래밍 방식으로 DB 연결 인스턴스를 사용하는 컨텍스트를 제공합니다. 그러나 그것은 각각의 DB 인스턴스에 대해 __enter____exit__을 호출하는 것보다 조금 더 복잡 할 것이며, 그렇게하려고 시도하지 않아도된다고 생각합니다. 그 목적을위한 것이 아닙니다. 이 경우 DB 인스턴스의 컨텍스트 관리자를 사용하여 직접 제안 할 것입니다.

def __enter__(self): 
    for db in self.pool: 
     with db as d: 
      d.transaction() 

def __exit__(self, type, value, traceback): 
    pass 

을하지만 오류하려면 자신을 처리 :

당신은 자신의 상황에 맞는 매니저를 사용하려면,이 같은 작업 것이다

def __enter__(self): 
    for db in self.pool: 
     try: 
      db.connection() 
      # ... write and transact here 

def __exit__(self, type, value, traceback): 
    if type is None: # no errors, so close as normal 
     for db in self.pool: 
      db.close() 
    # ... more code here for proper error handling 
+0

'A'는 'B'의 하위 클래스가 아니라 오히려 'B'_uses_ 'A'의 인스턴스입니다. – eddiewould

+0

성취하고자하는 바를 잘 나타내주기 위해 내 설명을 업데이트했습니다 (복합 컨텍스트 관리) – eddiewould

+0

@ 내 답변을 업데이트했습니다. –