python/기본
Decorator / contextmanager
wefree
2022. 4. 29. 20:24
def add_num(a, b):
return a + b
print('start')
r = add_num(1, 2)
print('end')
print(r)
####################################################################
# AOP 처럼 ...
def print_info(func):
def wrapper(*args, **kwargs):
print('start')
result = func(*args, **kwargs)
print('end')
return result
return wrapper
def add_num(a, b):
return a + b
# 첫번째 사용 방법
f = print_info(add_num)
r = f(1, 2)
print(r)
'''
start
end
3
'''
# 두번째 사용 방법
@print_info
def add_num_deco(a, b):
return a + b
r = add_num_deco(1, 2)
print(r)
####################################################################
def deco_1(func):
def wrapper(*args, **kwargs):
print('1-START')
result = func(*args, **kwargs)
print('1-END')
return result
return wrapper
def deco_2(func):
def wrapper(*args, **kwargs):
print('2-START')
result = func(*args, **kwargs)
print('2-END')
return result
return wrapper
# deco_1(deco_2(deco_test))(a, b) 로 실행된다고 생각하면 될 듯?
@deco_1
@deco_2
def deco_test(a, b):
return a + b
r = deco_test(1, 2)
print(r)
'''
1-START
2-START
2-END
1-END
3
'''
Python Clousure 에 나오는 functools.partial() 을 이용하면 아래처럼도 작성할 수 있다.
import functools
def add_num(a, b):
return a + b
def print_info(f):
print('start')
result = f()
print('end')
return result
if __name__ == '__main__':
f = functools.partial(add_num, 1, 2)
r = print_info(f)
print(r)
=====================================================================================
class 의 __enter__(), __exit__() 를 이용할 수 있다.
class CustomOpen(object):
def __init__(self, filename):
self.file = open(filename)
def __enter__(self):
return self.file
def __exit__(self, ctx_type, ctx_value, ctx_traceback):
self.file.close()
with CustomOpen('file') as f:
contents = f.read()
=====================================================================================
contextlib.contextmanager + yield 를 이용해 작성할 수도 있다.
import contextlib
@contextlib.contextmanager
def print_info(pre, post):
print(pre)
yield
print(post)
@print_info("start", "end")
def add_num(a, b):
return a + b
if __name__ == '__main__':
r = add_num(1, 2)
print(r)
위의 코드는 with 문으로 작성될 수 있다.
import contextlib
@contextlib.contextmanager
def print_info(pre, post):
print(pre)
yield
print(post)
def add_num(a, b):
return a + b
if __name__ == '__main__':
with print_info("start", "end"):
r = add_num(1, 2)
print(r)
참고 코드
import contextlib
@contextlib.contextmanager
def open_file(name):
f = open(name, 'wb')
yield f
f.close()
with open_file('some_file') as f:
f.wirte('Hola')
https://github.com/gto76/python-cheatsheet#context-manager 참고
class MyOpen:
def __init__(self, filename):
self.filename = filename
def __enter__(self):
self.file = open(self.filename)
return self.file
def __exit__(self, exc_type, exception, traceback):
self.file.close()
with open('test.txt', 'w') as file:
file.write('Hello World!')
with MyOpen('test.txt') as file:
print(file.read())