Python) with open(…) as f 에서 f의 정체는?
파이썬에서
with open(...) as f
를 많이 볼 수 잇다.
근데, with를 사용하지 않고
f = open(...)
이렇게 해서 open함수를 사용해주는경우도 있다(이 경우 f.close()반드시 해줘야함).
그런데, 두 경우에서 ‘f’ 는 마치 같은 녀석처럼 쓰인다.
만약 그렇다면, f는 open함수의 리턴값이니까, with A as B 에서 A는 B 와 같은 녀석인가??
결론부터 말하면, 일반적인 경우, 그렇지 않다.
open함수의 경우가 특별한 것이다.
with A as B: …
라고 하면,
A는 ‘context manager’ 가 되는 객체이고,
B는 [A.__enter__메서드의 리턴값] 이다.
‘context manager’가 되기 위해서는, __enter__메서드와 __exit__메서드를 가지고 있어야 한다.
(참고로, with 구문이 시작될때 바로 이 __enter__메서드가 호출되며, with 구문을 빠져나가면서 __exit__메서드가 자동으로 호출되는 것이다. with 구문에서 open함수를 사용할때 굳이 파일오브젝트를 close()해주지 않아도 되는 원리가 여기에 있다.)
자주 쓰이는
with open(...) as f: …
에서 open(…)함수가 리턴하는 객체는 ‘file object’ 인데, 이 객체는 __enter__와 __exit__ 메서드를 가지고있도록 만들어져있기 때문에 ‘context manager’로서 역할하게 된다.
그런데, 이 객체(open함수가 리턴하는 file object)의 __enter__메서드는 리턴값이 self다. 즉, file object 자신을 리턴하게 되어있다.
따라서, with open(…) as f 에서 f는 open(…)함수가 리턴한 file object가 되는것이다.
그렇기 때문에,
f = open(…)try: print(f.read())finally: f.close()
위와같이 with 를 쓰지 않고 open함수 사용시 f=open(…)이라고 해줄때의 f와, 위에서의 with open(…) as f 에서의 f가 결과적으로는 같은녀석이 되는것이다(둘 다 open함수가 리턴하는 file object가 된다).
하지만, 직접 context manager 클래스를 만들어 줄 경우, __enter__메서드의 리턴값을 self로 하지 않을수도 있기 때문에, with A as B에서 A와 B는 같지 않다.
많이 쓰이는 with open(…) as f 구문 때문에 괜히 헷갈리지 말자!