// contextlib.contextmanager
import contextlib
# 데코레이터를 가독성 높게 사용할 수 있다.
@contextlib.contextmanager
def tag(name):
print('<{}>'.format(name))
yield
print('<{}>'.format(name))
#방법 1
@tag('h2')
def f(content):
print(content)
f('test')
"""
출력 :
<h2>
test
<h2>
"""
#방법2
with tag('h2'):
print('test')
"""
출력 :
<h2>
test
<h2>
"""
#방법3(확장해보자!!)
def f():
print('확장가능하다')
with tag('h2'):
print('h2:test')
with tag('h3'):
print('he:test')
f()
"""
출력:
확장가능하다
<h2>
h2:test
<h2>
<h3>
he:test
<h3>
"""
================================================================================
//contextlib.ContextDecorator
import contextlib
class tag(contextlib.ContextDecorator):
def __init__(self,name):
self.name = name
self.start_tag = '<{}>'.format(name)
self.end_tag = '<{}>'.format(name)
def __enter__(self): #클래스가 들어올때 실행
print(self.start_tag)
def __exit__(self, exc_type, exc_val, exc_tb): #클래스 끝날때 실행
#에러 헨들링도 가능하다!
print(exc_type) #<class 'Exception>
print(exc_val) # err
print(exc_tb) #<traceback object at 0x00000215D7A76BC8>
print(self.end_tag)
with tag('h2'):
raise Exception('err') #에러헨들링 테스트를 해보자!
print('test')
================================================================================
//contextlib.suppress
import contextlib
import os
try:
os.remove('test.txt')
except FileNotFoundError:
pass
#위를 더 깔끔하게 적을 수 있다.
with contextlib.suppress(FileNotFoundError):
os.remove(('test.txt'))
================================================================================
//contextlib.redirect_stdout / contextlib.redirect-sterr
import contextlib
import logging
with open('stdout.log','w') as f: #stdout.log파일을 생성한다.
with contextlib.redirect_stdout(f):
print('hello') #stdout.log파일에 hello라고 입력.(터미널에는 출력안됨)
with open('stderr.log','w') as f: #stderr.log파일을 생성한다.
with contextlib.redirect_stderr(f):
logging.error('Error!') #로깅 정보가 stderr.log파일에 입력 된다.
"""
이렇게 쓰는 이유는 help 정보를 다른 곳에 적거나 일부 logging정보를 다른 곳에 적고싶을때 많이 쓴다.
"""
================================================================================
//contextlib.ExitStack
import contextlib
def is_ok_job():
try:
print('do something')
#일부러 에러를 발생시켜보자
raise Exception('error')
return True
except Exception:
return False
def cleanup():
print('clean up')
def cleanup2():
print('clean up2')
with contextlib.ExitStack() as stack:
stack.callback(cleanup2) #stack에 콜백시키면 이 함수의 마지막에 불리게 된다!!
stack.callback(cleanup)
@stack.callback #위와 같음 == stack.callback
def cleanup3():
print('clean up3')
is_ok = is_ok_job()
print('more task')
# 만약에 에러가 없다면. stack안에 있는 함수를 전부 pop시킨다(안부른다)
# 때문에 is_ok가 True라면 위의 stack.callback이 불리지 않는다!
if is_ok:
stack.pop_all()
"""
출력 :
do something
more task
clean up3
clean up
clean up2
"""
================================================================================
//collections.ChainMap
import collections
a = {'a':'a','c':'c','num':0}
b = {'b':'b','c':'cc'}
c = {'b':'bbb','c':'ccc'}
m = collections.ChainMap(a,b,c)
print(m) #ChainMap({'a': 'a', 'c': 'c', 'num': 0}, {'b': 'b', 'c': 'cc'}, {'b': 'bbb', 'c': 'ccc'})
print(m.maps) #[{'a': 'a', 'c': 'c', 'num': 0}, {'b': 'b', 'c': 'cc'}, {'b': 'bbb', 'c': 'ccc'}]
m.maps.reverse()
print(m.maps) #[{'b': 'bbb', 'c': 'ccc'}, {'b': 'b', 'c': 'cc'}, {'a': 'a', 'c': 'c', 'num': 0}]
print(m['c']) #ccc ->가장 앞에있는 사전형의 c를 가져온다
m.maps.insert(0,{'c':'cccccc'})
print(m.maps) #[{'c': 'cccccc'}, {'b': 'bbb', 'c': 'ccc'}, {'b': 'b', 'c': 'cc'}, {'a': 'a', 'c': 'c', 'num': 0}]
print(m['c']) #cccccc
del m.maps[0]
print(m.maps) #[{'b': 'bbb', 'c': 'ccc'}, {'b': 'b', 'c': 'cc'}, {'a': 'a', 'c': 'c', 'num': 0}]
print(m['c']) #ccc
m['b'] = 'BBBBBBB'
print(m.maps) #[{'b': 'BBBBBBB', 'c': 'ccc'}, {'b': 'b', 'c': 'cc'}, {'a': 'a', 'c': 'c', 'num': 0}]
------------------------------------
import collections
a = {'a':'a','c':'c','num':0}
b = {'b':'b','c':'cc'}
c = {'b':'bbb','c':'ccc'}
class DeepChainMap(collections.ChainMap):
def __setitem__(self, key, value):
for mapping in self.maps:
if type(mapping[key]) is int and mapping[key] < value:
mapping[key] = value
return
self.maps[0][key] = value
m = DeepChainMap(a,b,c)
#TEST 1
m['num'] = 1
print(m) #DeepChainMap({'a': 'a', 'c': 'c', 'num': 1}, {'b': 'b', 'c': 'cc'}, {'b': 'bbb', 'c': 'ccc'})
#TEST2(TEST1을 지우고 테스트 하세요)
m['num'] = -1
print(m) ##DeepChainMap({'a': 'a', 'c': 'c', 'num': 0}, {'b': 'b', 'c': 'cc'}, {'b': 'bbb', 'c': 'ccc'})
================================================================================
//collections.defaultdict
import collections
d = {}
l = ['a' , 'a' , 'a' , 'b' , 'b' , 'c']
for word in l :
if word not in d:
d[word] = 0
d[word] += 1
print(d) #{'a': 3, 'b': 2, 'c': 1}
#-- 위와 같음---#
d = {}
l = ['a' , 'a' , 'a' , 'b' , 'b' , 'c']
for word in l:
d.setdefault(word,0)
d[word] += 1
print(d) #{'a': 3, 'b': 2, 'c': 1}
#-- 위와 같음---#
d = collections.defaultdict(int) #제일 처음은 디폴트로 0이 들어간다
l = ['a' , 'a' , 'a' , 'b' , 'b' , 'c']
for word in l:
d[word] += 1
print(d) #defaultdict(<class 'int'>, {'a': 3, 'b': 2, 'c': 1})
#-- collection.default 다른 예제---#
d = collections.defaultdict(set)
s = [('red' , 1), ('blue' , 2), ('red',3), ('blue',4), ('red',1), ('blue',4)]
for k,v in s:
d[k].add(v)
print(d) # {'red': {1, 3}, 'blue': {2, 4}})
================================================================================
//collections.Counter
l = ['a' , 'a' , 'a' , 'b' , 'b' , 'c']
c = collections.Counter()
for word in l:
c[word] += 1
print(c) #Counter({'a': 3, 'b': 2, 'c': 1})
print(c.most_common(1)) #[('a', 3)] -> 랭킹 1까지(순위 같은거 매길때 유용하게 사용된다.)
print(c.most_common(2)) #[('a', 3), ('b', 2)] ->랭킹 2까지
print(c.values()) #dict_values([3, 2, 1])
print(sum(c.values())) #6
================================================================================
//collections.deque
import collections
import queue
collections.deque
q = queue.Queue()
lq = queue.LifoQueue()
l = []
d = collections.deque() #list보다 훨씬 빠르고, 메로리 부담을 던다.
for i in range(3):
q.put(i)
lq.put(i)
l.append(i)
d.append(i)
for _ in range(3):
#선입선출
print('FIFO quene = {}'.format(q.get()))
#후입선출
print('LIFO quene = {}'.format(lq.get()))
# 선입선출
print('list = {}'.format(l.pop()))
print('deque = {}'.format(d.pop()))
#후입선출
# print('list = {}'.format(l.pop(0)))
# print('deque = {}'.format(d.popleft()))
print()
d.rotate() #순서 뒤집기
d.extendleft('x') #왼쪽에 x 추가
d.extend('y') #오른쪽에 y추가
"""
출력 :
FIFO quene = 0
LIFO quene = 2
list = 2
deque = 2
FIFO quene = 1
LIFO quene = 1
list = 1
deque = 1
FIFO quene = 2
LIFO quene = 0
list = 0
deque = 0
"""
================================================================================
//collections.deque