2019년 12월 19일 목요일

파이썬 with 구문 ( Context manager 사용 방법)

이 방법은 아마도 python 2.5에서  추가된 기능입니다.

with~as 구문을 사용하는 방법인데, 이게 아마도 고대의 유물인 Lisp 같은 언어에서는 쓰는 매크로 형태와 비슷한 구문입니다.  (with-open-file 같은 구문)

with open('filename.txt','w') as f:
  blabla.. 


대략 이런식으로 사용합니다.

기존에 file processing을 하는 경우 open -> context -> close 형태로 사용하고,
이중에 file open 이 fail 되었을 경우 등등 예외처리를 해주었는데,

아무래도 실제 본질 보다는 파일 access이런게 제대로 되었는지에
신경을 쓸 수 밖에 없고 이런부분이, 생각의 흐름을 방해하는 요소중의 하나였는데

이 context manager를 사용하는 경우,
이런 예외처리 부분들이나,  with로 ,, 생각의 흐름을 방해하지 않게,
 상당히 간략하게 표현이 됩니다.

또 이런 부분들이, 아래와 같이,,
__enter__ ,
__exit__ (self, type, value, traceback)  # 예외 발생시 처리 하는 인자들,


함수들을 override하여서, 아래와같이 class안에서 구현이 가능하기도 하고,






class Logger(object):
  __enter__(self):
    ''' enter process '''
  __exit__(self, type, value, traceback):
    ''' exit process '''



아래와 같이 단순 function에 decorator 형태로 @contextmanager 를 함수위에 추가하여
context manager를 추가할 수 도 있습니다.


@contextmanager
def log:
  try:
    ''' log file open and process '''
  finally:
    ''' log file close process ''' 



이 with 구문의 사용은 주로 file ,socket, db  access 라든지 login process 등등에서 활용이 가능하고, 이 with 구문의 활용은 사실 무궁무진합니다

그렇지만 그중에서도 결국 가장 많이 사용하는 부분은 File I/O에서 일텐데,

이중에 동시에 파일을 열고 닫는 경우은 아래와 같은식으로도 사용이 가능합니다
예를 들면,

with open("file1", "r") as src:     
  with open("file2", "w") as dst:         
    dst.write(src.read())


이렇게 사용할 수도 있지만, 위와 같이 동시에 사용하는 것 보다는
아래와 같이 하나의 statement로 묶는 것이 좀더 간결해보입니다.


with open("file1", "r") as src, open("file2", "w") as dst:
  dst.write(src.read())

즉. 위와 같은 한 문장으로 동시에 여는 형태로 사용할 수도 있습니다.



2019년 12월 14일 토요일

파이썬, for ... else .. 사용법


파이썬에는 for문에 특이한 else기능이 하나 더 있습니다.

이것은 일종의 syntax sugar같은 것인데,

이런 문법들을 사용하면, 간결해지면서 가독성이 좋아지죠,,
(단 문법을 알고 있다는 전제로 입니다. )

이 방법의 사용예는

for문을 사용하다보면, 루프 중간에 break 문으로 빠져나오는 경우들이 있는데,
이게 break문이 걸려서 빠져나가는지 아닌지를 판단이 필요한 경우가 있습니다.

보통은  flag등을 둬서, 처리하는게 기존의 방식이라면,
for문과 같은 레벨에 else를 둬서 break없이 빠져나온 경우를 처리하는 방법입니다.




for x in range(4):
  if x == 2:
    print ('loop out')
    break
else:
  print ('loop end')



위 예제의 경우는 x =2 에서 루프를 빠져나오기때문에, else문이 실행이 되지 않고
'loop out' 이 출력이 되고,



for x in range(4):
  # nop
  pass
else:
  print ('loop end')


위와 같은 경우는 , for loop가 break없이 빠져나왔으므로 'loop end' 가 출력이 된다.




2019년 12월 12일 목요일

파이썬, ==, is 의 차이





  • == 는 값을 비교 한다. 실제로 값을 비교해서 같은지 return을 돌려줌
  • is 는 reference를 비교한다. 두개가 같은 object인지를 비교함.   



그래서, is  로 비교하는 것은 object들을 비교할때는 유용하나,

== 으로 비교하는 것과 결과가 다를 수 있다.




a = [1,2,3]
b = a 
b is a # True
b == a # True

b = a[:] # slice operator로 다시 list를 생성
b is a  # False, 다른 object
b == a  # True, 다른 object이나 값이 같음. 
https://stackoverflow.com/questions/132988/is-there-a-difference-between-and-is?rq=1

2019년 12월 10일 화요일

파이썬 정규식 regex Grouping



Grouping

정규식에서 ( )괄호는 그룹을 이야기합니다.
이 Grouping은 꽤 유용한 방법중의 하나입니다.

각각의 매칭을 MatchObject로 넘기며, 크게 아래와 같은 두가지 방법이 있습니다.

  1. 순서대로 가져오는 방법 
  2. 이름을 지정해서 가져 오는 방법


Ordered Group

이 중 순서대로 가져오는 방법은 group(0) : 전체,
group(1) : 첫번째 괄호
group(2) : 두번째 괄호
이런식으로 전개할 수 있으며, 아래와 같이 전화번호 같은 것을 매칭을 할떄,
아래와 같은 형태로 매칭이 됩니다.


import re
p = re.compile('([\d]+)_([\d]+)')
m = p.search('345-1234')
m.group(0) # 345-1234
m.group(1) # 345
m.group(2) # 1234




Named Groups

이름에 매핑하는 방법은, 아래와 같이 작성해서, dictionary로 반환을 받는 방법입니다.
(?P<name>pattern)


import re
p = re.compile('(?P[\d]+)_(?P[\d]+)')
m = p.search('345-1234')
m.group(0) # 345-1234
m['first'] # 345
m['second'] # 1234

정규식에서 다시 값을 추출해서 특정 용도로 사용할때 , 중간단계를 사라지게 해서
편한 방법중 하나 입니다.


Back references 

back referencing(역참조)의 \1은 처음 사용한 표현식과 일치한다는 이야기입니다.
마찬가지로 \2, \3은 두번째 세번째 사용한 표현식과 일치한다는 것이고,
이 것은 주로 패턴이 반복되어서 나올때에 사용합니다

그리고, substitute (치환)을 할때, 매칭을 다시 가져다 쓸 때 사용합니다.
주로 언제 사용하냐면 순서를 바꿀때, 예를 들면, 첫번째 매칭이랑 두번째 매칭을 순서를 바꿀때, 이 방법이 유용합니다.

import re
p = re.compile('(?P[\d]+)_(?P[\d]+)')
m = p.sub('P\2_M\1','345-1234')
m # P1234_M345