2011-08-19 2 views
3

파이썬의 with 문을 실험하고 있는데, __exit__ 메서드가 한 번 호출되는 동안 내 __init__ 메서드가 두 번 호출되는 코드를 발견했습니다. 이것은 아마도이 코드가 아무런 도움이되지 않는다면 리소스 누출이 일어날 것임을 의미합니다. 내가 효과적으로 생성자를 직접 호출의 with 문에 뭔가 잘못하고 있어요 그것 때문에 추측하고있어문이있는 파이썬

Constructing MyResource 
Entering MyResource 
Constructing MyResource 
Some function 
Cleaning up MyResource 

:

class MyResource: 
    def __enter__(self): 
     print 'Entering MyResource' 
     return MyResource() 

    def __exit__(self, exc_type, exc_value, traceback): 
     print 'Cleaning up MyResource' 

    def __init__(self): 
     print 'Constructing MyResource' 

    def some_function(self): 
     print 'Some function' 

def main(): 
    with MyResource() as r: 
     r.some_function() 

if __name__=='__main__': 
    main() 

프로그램의 출력입니다. 이 문제를 어떻게 해결합니까?

+0

답변 해 주셔서 감사합니다. 뒤늦은 지경에서 지금은 분명히 분명합니다. :) – CadentOrange

답변

19

__enter__에서 새 인스턴스를 반환하지 않아야합니다. 대신, self (__enter__가 호출되고있는 인스턴스를 돌려 그 두 번 이유 __init__()라고 - 당신이 __enter__()에 한 번, 당신과 문에 한 번, 두 번 전화를 여기에 올바른 버전입니다 :..

def __enter__(self): 
    print 'Entering MyResource' 
    return self 
3

내 추측은 self가 이미 구축 클래스의 인스턴스 인 당신이하지 return MyResource()하지만 return self을 할 것입니다

6

__init__가 두 번 호출하기 때문에 두 번 호출되고있는 이유는.

을 한 번 할 때를 with 문에서 MyResource 객체를 시작하고 한 번 더 with 문을 다시 작성하고 대신 self을 반환해야 MyResource

귀하의 __enter__ 방법의 다른 인스턴스를 반환 __enter__ 호출 할 때.

2
가 코드를 변경

:

def __enter__(self): 
    print 'Entering MyResource' 
    return self 

__enter__ 방법은 당신이 당신의 인스턴스를 만들 수 없습니다, 초기화를 수행하는이, 이미 (자기)이 존재한다.