2014-10-13 9 views
26

예외가 발생하는 경우 객체의 마무리를 보장하는 수단으로 python의 with 문을 사용하는 것에 익숙합니다. 이것은 일반적으로 보이는"as"키워드가없는 "with"문의 의미

f = file.open('myfile.txt'): 
try: 
    do stuff... 
finally: 
    f.close() 

또는 마무리 다른 어떤 루틴 클래스가 제공 할 수 있습니다에 대한 짧은 손으로

with file.open('myfile.txt') as f: 
    do stuff... 

있다.

내가 최근에 발표 OpenGL을 다루는 코드의 조각을 건너 온 :

with self.shader: 
    (Many OpenGL commands) 

참고 그 어떤 as 키워드의 부재. 이것은 클래스의 __enter____exit__ 메소드가 여전히 호출되지만 객체가 블록에서 명시 적으로 사용되지 않는다는 것을 나타 냅니까 (즉, 전역 또는 암시 적 참조를 통해 작동합니까?) 아니면 나를 잊어 버리는 다른 의미가 있습니까?

+2

'with'블록 내에 컨텍스트 관리자의 별명을 지정할 필요가 없다면 괜찮습니다. ['contextlib.suppress'] (https://docs.python.org/3.4/library/contextlib.html#contextlib.suppress). 엄밀히 말하면, 당신은'open (...) : ... '을 할 수 있습니다.하지만 파일 핸들러에 접근 할 수 없기 때문에 많은 부분이 없습니다! – jonrsharpe

답변

30

as이라는 식별자에 할당 할 개체를 반환 할 수 있습니다. as에 의해 할당 된 __enter__ 메서드에 의해 반환 된 개체이며 반드시 컨텍스트 관리자 자체는 아닙니다. as <identifier>를 사용

당신이 새로운 개체를 만들 때 open() 호출하는 것처럼, 도움이되지만 모든 컨텍스트 관리자는 단지 컨텍스트 생성됩니다. 예를 들어 재사용이 가능하며 이미 만들어져 있습니다.

데이터베이스 연결을 가져 가십시오. 데이터베이스 연결을 단 한 번만 만들지 만 많은 데이터베이스 어댑터를 사용하면 연결을 컨텍스트 관리자로 사용할 수 있습니다. 컨텍스트를 입력하고 트랜잭션이 시작되고, 그것을 종료하고 트랜잭션 (성공) 커밋하거나, 또는 롤백 (예외가있을 때) : 새로운 오브젝트가 여기에, 생성 할 필요가 없습니다

with db_connection: 
    # do something to the database 

은 문맥은 db_connection.__enter__()으로 입력되고 db_connection.__exit__()으로 다시 종료되지만, 우리는 이미 이 연결 개체에 대한 참조를 가지고 있습니다.

이제 일 수 있습니다. 입력하면 연결 개체가 커서 개체를 생성합니다. 지금은 로컬 이름이 커서 오브젝트를 할당하는 의미가 있습니다 :

with db_connection as cursor: 
    # use cursor to make changes to the database 

db_connection

여전히 이미 이전에 존재, 여기에 호출되지 않은, 우리는 이미에 대한 참조를 가지고있다. 그러나 db_connection.__enter__()이 무엇이든 이제 cursor에 할당되며 거기에서부터 사용할 수 있습니다.

이것은 파일 개체에서 발생합니다. open()는 파일 객체를 반환하고, 당신이 withopen() 전화를 사용할 수 있으며 오히려이보다 한 단계에서 새로 생성 된 개체에 대한 참조를 할당 할 수 있도록 fileobject.__enter__()는, 파일 객체 자체를 반환합니다.그 작은 트릭 없이는 다음을 사용해야합니다.

f = open('myfile.txt') 
with f: 
    # use `f` in the block 

모든 것을이 쉐이더 예제에 적용합니다. 이미 self.shader에 대한 참조가 있습니다. self.shader.__enter__()self.shader에 대한 참조를 다시 반환 할 가능성은 매우 높습니다. 그러나 이미 완벽하게 서비스 가능한 참조가 있으므로 그 지역을 새로 만드는 이유는 무엇입니까?