NOTICE!! 현재 블로그로 게시글 이전 작업 진행중입니다.

2 minute read


1. 인덱스&슬라이싱

간단하지만 파이썬 스러운 인덱싱 방법을 다루고 있다.

# 숫자 리스트
num_list = [4,6,2,6,8]

# 위와 같은 숫자리스트중 마지막 원소를 파이써닉하게 뽑는 방법
num_list[4] (x)
num_list[-1] (O)

파이썬스러움의 대표적인 한가지는 시작을 0부터 하고 마지막원소를 뒤에서부터 마이너스로 접근할 수 있다는 점이다. 파이썬을 배우는 사람들은 누구나 편하게 쓰지만, 다른언어를 배우고 온 사람들에게는 혼란이 올 수 있는 부분이다.


2. 컨텍스트 관리자(context manager)

컨텍스트 관리자는 사전 조건과 사후조건이 필요한 일부 코드를 실행할 때 훌륭하게 사용할 수 있는 도구이다.

예를들어서 특정 파일을 열고난 후 , 작업이 끝나면 누수를 막기위해 꼭 닫아주어야 한다. 혹은 생성된 임시파일이 있다면 메모리 관리를 위해서 적절하게 삭제를 해주어야 한다.

파이썬에서 기본적으로 finally를 통한 간단한 방법이 있다.

fd = open(filename)
try:
	process_file(fd)
finally:
	fd.close()

위에 있는 코드처럼 finally 구분에 닫는것을 넣어둔다면 try절이 실행이 잘되거나 혹은 잘못되어도 상관없이 안정적으로 닫을 수 있게된다.

이를 좀 더 파이써닉하게 바꾸면 아래와 같다.

with open(filename) as fd:
	process_file(fd)

with문은 컨텍스트 관리자로 진입하게 되는데 이때 __enter와 ____exitwith문은 컨텍스트 관리자로 진입하게 되는데 이때 ____enter와 ____exit 두개의 매직 메서드를 가지고 있다. __ 두개의 매직 메서드를 가지고 있다. 위 코드의 첫번째 줄에서 with문은 __enter메서드를 호출하고 마지막 줄에서 ____exit__메서드를 실행함으로서 자동을 파일을 닫게된다.

또한 다른용도로서 관심사를 분리하고 독립적으로 유지되어야 하는 코드를 분리하는 좋은방법이 “컨텍스트관리자” 이다.

예를들어 데이터 베이스를 빽업해야 하는 경우를 생각해보자. 이때 주의사항은 오프라인 상태에서 해야하는것이다. 즉, DB가 실행되지 않는 상황에서 해주어야 하는것이다.

그렇다면 사전에 서비스를 중지를 시키고 -> 백업을 실행하고 -> 백업이 완료가 되면 프로세스를 다시 시작시켜야한다.

아래 코드를 천천히 따라가면서 예시를 이해해보면 될거같다.

def stop_database():
	run("systemctl stop postgresql.service")
    
def start_database():
	run("systemctl start postgresql.service")

class DBHandler:
	def __enter__(self):
    	stop_database()
        return self
    def __exit__(self, exc_type, ex_value, ex_traceback):
    	start_database()
    def db_backup():
    	run("pg_dump database)
    def main():
    	with DBHandler():
        	db_backup()

일단 위의 코드는 DBHandler 클래스 내부에 컨텍스트 관리자를 사용하지 않은 모습이다. 이것을 컨텍스트 관리자를 사용하여 표현하면 아래와 같다.

import contextlib

@contextlib.contextmanager
def db_handler():
	try: 
    	stop_database()
        yield
    finally:
    	start_database()

with db_handler():
	db_backup()

변환된 함수의 설명을 하면 이렇다. 먼저 제너레이터 함수를정의를 하고 @contextlib.contextmanager데코레이터를 적용한 모습이다.

데코레이터를 적용하게되면 yield문 앞에 있는 모든 내용을 __exit__ 메서드의 일부로 취급된다고 보면된다. 그리고 yield다음에 오는 내용들을 “__exit__” 메서드라고 보면된다.

이렇게하면 기존함수를 리팩토링하기 쉬워진다는 장점이 있다. 어떤 특정 객체에도 속하지 않은 컨텍스트 관리자가 필요한 경우 좋은 방법이다.


3. 컴프리헨션과 할당표현식

아래처럼 컴프리헨션을 사용하면 가독성이 높고 코드를 간결하게 쓰는 효과를 준다.

# 컴프리헨션 미적용
numbers = []
for i in range(15):
	numbers.append(run_calculation(i))
# 컴프리헨션 적용
numbers = [run_calculation(i) for i in range(10)]

하지만 컴프리헨션은 조건이 간단할 때 사용하기 편하지만 조건이 복잡하다면 오히려 for문을 사용하는것이 훨씬 간단하다. 이때 사용할 수 있는 것이 “할당 표현식”이다.

할당표현식은 표현식안에서 변수에 값을 할당하는 방법이며 -> := 와 같이 사용합니다.

변수 :=값

hello = 'Hello, world!'

if (length := len(hello)) >= 10:
	print(f"length는 {length}, 10 이상")
>>> length는 13, 10이상

컨프리헨션은 가독성을 생각해야 하며, 정말로 이해하기 쉬운 간결한코드로 작성을 마치지 못한다면 한줄로 만들기 위해 애쓰기보다는 그냥 for문이나 할당표현식을 활용해라.

Leave a comment