ABOUT ME

-

Today
-
Yesterday
-
Total
-
choco@desktop:~/tistory
$ 정보처리기사 요점정리
1과목 2과목 3과목 4과목 5과목 실기

$ Linux Kernel
Power Management DVFS
  • Python 숏코딩을 위한 팁 정리
    SW개발/Python 2020. 1. 23. 22:23

    ** Python 강의를 기반으로 추후 기억해두고 싶은 내용을 정리한 문서입니다. 숏코딩을 위한 수업은 아니었지만 python 문법 강의에서 도움이 되었던 부분들을 정리했습니다.

     

     

    1. look up table 활용하기

    룩업테이블을 사용하는 것은 런타임에 계산하지 않고 미리 배열로 저장해둔 것을 활용하는 방식입니다. 예를 들어, 학생 성적을 구할 때 90~100 점은 A, 80~89점은 B, 70~79점은 C... 이런식으로 성적을 매긴다면, 이를 if문으로 일일히 나누지 않고 룩업 테이블을 만들어 활용할 수 있습니다.

    (참고) 인생의 절반 손해봤어요

    def get_grade(score):
    	return "FFFFFFDCBAA"[score//10]
        
    get_grade(91)

    + 딕셔너리를 활용하여 룩업 테이블을 사전에 만들어두는 경우도 많습니다. 딕셔너리를 간편하게 만들고자 할 때는 zip을 활용하는 방법이 있습니다. 

    # zip을 활용하여 딕셔너리 만드는 방법
    my_dict1 = dict(zip(['one', 'two', 'three'], [1,2,3]))
    
    # 그 외 기본적인 딕셔너리 생성 방법들
    my_dict2 = dict(one=1, two=2, three=3)
    my_dict3 = dict([('one', 1), ('two', 2), ('three', 3)])
    my_dict4 = {'one':1, 'two':2, 'three':3}
    
    print(my_dict1['one'])

     

    2. statement는 최대한 expression으로 대체하기

    statement는 실행가능한 최소한의 독립적인 코드를 의미합니다. 우리가 보통 보는 한 줄의 코드가 대부분 statement에 속할 것입니다. expression은 한 개의 객체로 evaluate될 수 있는 것을 의미합니다. 하나의 변수에 담을 수 있는 객체로, 문자열, 비교 연산 등이 이에 속합니다.

    그런데, 많은 긴 statement들을 간단한 expression으로 표현할 수 있습니다.

     

    (1) for statement => comprehension

    statement

    for i in [1,3,5,7,9]:
    	print(i, end=' ')

    expression

    print(*(i for i in [1,3,5,7,9]), end=' ')
    # print() 안에 generator가 오면 바로 결과를 볼 수 없어서 *을 이용하여 unpack을 하였습니다.
    
    # 오류나는 코드 예시:
    # print(i for i in [1,3,5,7,9], end=' ')
    
    # 출력이 원하는 대로 되지 않는 코드 예시:
    # print((i for i in [1,3,5,7,9]), end=' ')

     

    (2) if statement => conditional expression / comprehension

    if가 필요한 상황을 만들기 위해서, 2의 배수면 YES를, 2의 배수가 아니면 NO를 출력하는 코드를 작성해보겠습니다.

    statement

    def check(num):
    	if num % 2: return 'NO'
    	else: return 'YES'
    
    print(check(4))

    conditional expression

    # 1 if else
    def check(num):
    	return 'NO' if num % 2 else 'YES'
        
    # 2 and or
    def check(num):
    	return num % 2 and 'NO' or 'YES'
        
    print(check(4))

    + for expression에 if 를 추가로 사용하는 경우

    아래 예시는 위의 (1) for statement에서와 동일한 출력 결과가 나옵니다. 이와 같이 if 를 이용하여 expression 을 더욱 다양하게 구성할 수 있습니다.

    print(*[i for i in range(1, 10) if i % 2], end=' ')

     

    (3) def function => lambda function

    기본적인 함수의 경우 다음과 같은 형태를 가지고 있는데,

    def function_name(parameter1, parameter2):
    	return return_value

    람다 함수는 이름 없는 함수라 불리듯이 function_name이 없습니다. 그 외에 parameter나 return 값은 동일하게 가지고 있기 때문에 일반 함수와 거의 동일하게 사용할 수 있습니다.

    lambda parameter1, parameter2: return_value

    예를 들어, sort를 하는 경우 lambda 함수가 많이 활용됩니다. 이 자리에는 일반 함수가 들어갈 수도 있지만,

    # sort할 데이터, 나이를 오름차순으로 정렬할 것!
    Blackpink = [
    	('Jennie', 24), 
        ('Rose', 23), 
        ('Lisa', 22), 
        ('Jisoo', 25)]
    def my_sort(x):
    	return x[1]
    
    Blackpink.sort(key=my_sort)

    lambda 함수를 사용하는 경우 훨씬 짧게 작성이 가능합니다.

    Blackpink.sort(key=lambda x:x[1])

     

    3. 최대한 공식을 활용하기

    반복문 > comprehension > 공식 순으로 훨씬 더 짧게 코드를 작성할 수 있습니다.

    (+ 이에 더해서 실행 시간도 빠르게 할 수 있습니다.)

     

    예를 들어, 1부터 N까지의 합을 구하는 경우,

    (1) for 루프를 이용하는 경우: for문을 돌면서 1부터 n까지 합을 구합니다.

    def my_sum(num):
        ans = 0
        for i in range(1, num+1):
            ans += i
        return ans
    
    print(my_sum(10))

     

    (2) iterable 혹은 comprehension을 이용하는 경우

    # 1 iterable
    def my_sum(num):
        return sum(range(1, num+1))
    
    # 2 comprehension
    def my_sum(num):
        return sum([i for i in range(1, num+1)])
    
    print(my_sum(10))

     

    (3) 공식 활용

    1부터 n까지 합을 더하는 공식은 n * (n+1) / 2 입니다. 해당 공식을 이용하면 코드를 굉장히 줄일 수 있습니다.

    (참고) 가우스와 등차수열

    def my_sum(num):
        return num * (num+1) // 2
    
    print(my_sum(10))

     

    4. short circuit 활용

    논리 연산을 할 때는 A and B 인 경우 둘 모두가 참이여야만 결과가 참이 됩니다. 파이썬에서는 short circuit을 이용하기 때문에 A가 거짓인 경우 B는 아예 실행도 되지 않습니다. 이런 식으로 더 빨리 연산을 끝낼 수 있는 것입니다. 이는 or도 마찬가지입니다. or은 둘 중 하나만 참이면 결과가 참이 나오기 때문에 A or B일 때 A가 참이라면 역시 B는 실행되지 않습니다.

    이를 활용하면 if else 처럼 사용할 수도 있습니다. 아래는 학생의 점수를 받아서 구간 별로 A학점, B학점.. 등으로 점수를 매기는 코드의 예시입니다. 

    def function(score): 
    	return score >= 90 and 'A' or score >= 80 and 'B' or score > 70 and 'C' or 'F'
        
    print(function(81))

    + short circuit은 다음과 같은 경우에 유용하게 사용됩니다. 만일 어떤 홈페이지에 아이디가 존재하지 않는다면 비밀번호를 찾는 함수에서 오류가 날 수 있으므로 id가 존재하는 경우에만 다음으로 넘어가게 합니다.

    print(check_id('admin') and check_password('admin', '1234'))

     

    5. join을 이용하여 print() 한번에 출력 다 하기

    결과가 list 등 다양한 컨테이너로 얻어졌을 때 이를 for문을 돌면서 print() 하는 것 대신에, join으로 한 번에 묶어서 출력할 수 있습니다. 예를 들어, 연산의 결과로 다음과 같은 결과가 나왔다고 가정해 봅니다.

    ans1 = [2, 0, 2, 0]
    ans2 = [2, 0, 1, 9]

    이를 다음과 같이 출력할 수도 있을 것입니다.

    # 1 for 문 사용
    for i in ans1: print(i, end=' ')
    print()
    for i in ans2: print(i, end=' ')
    
    # 2 unpack 사용
    print(*ans1, end=' ')
    print()
    print(*ans2, end=' ')

    하지만 이를 join을 이용하여 합칠 수 있습니다. 이 방식은 코드가 짧아지는 것이 아닐 수 있지만, 웬만한 출력은 한 줄로 할 수 있다는 장점이 있습니다.

    print('\n'.join([' '.join(map(str, ans1)), ' '.join(map(str, ans2))]))
    # join은 문자열을 대상으로 하는 함수이기 때문에 map 함수를 사용하여 숫자를 문자열로 변경하였습니다.

     

    6. 유용한 bulit in 함수들

    map, filter, enumerate, eval, exec 등 유용한 함수들을 알아두고 사용하면 좋습니다.

    # 1 map은 컨테이너의 모든 요소에 원하는 함수를 적용할 수 있습니다.
    int2str = list(map(str, [1,2,3,4]))
    print(int2str)
    
    # 2 filter는 컨테이너의 요소들 중 조건에 해당하지 않으면 걸러냅니다.
    target = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    result = filter(lambda x : x%2, target)
    print(list(result))
    
    # 3 enumerate는 컨테이너의 인덱스와 요소의 값을 반환합니다.
    target = [5, 4, 3]
    for index, value in enumerate(target):
    	print(index, value)
    
    # 4 eval은 문자열 형태의 expression을 실행합니다.
    print(eval('1+2+3'))
    
    # 5 exec은 문자열 형태의 statement를 실행합니다. 
    exec('a = [1,2,3,4]')
    print(a)

     

    + 시간 확인

    파이썬 코드를 수정하였을 때 시간이 어떻게 달라졌는지 확인하고 싶다면 time 모듈을 활용합니다.

    import time
    
    # 1 for statement
    start = time.time() # 시작 시간
    
    ans = 0
    for i in range(1000000):
    	if i % 2: ans += i
    
    print("time 1 :", time.time() - start)  # 현재시각 - 시작시간 = 실행 시간
    
    # 2 for expression
    start = time.time() # 시작 시간
    
    ans = sum(i for i in range(1000000) if i%2)
    
    print("time 2 :", time.time() - start)  # 현재시각 - 시작시간 = 실행 시간

     

    + 최적화 확인

    파이썬 코드가 실행시 최적화되었는지 여부를 확인하기 위해서는 disassembler 모듈을 활용할 수 있습니다. 해당 코드가 CPython interpreter에서 어떤 식으로 실행되는지를 볼 수 있습니다.

    (참고) dis 모듈 설명

    import dis
    
    def my_func1():
        a, b, c = 2019, 2020, 2021
    
    def my_func2():
        a = 2019
        b = 2020
        c = 2021
    
    print("my_func1:")
    dis.dis(my_func1)
    
    print("my_func2:")
    dis.dis(my_func2)

     

    64 parameter

    78 statement와 expression

    140 딕셔너리 생성 (zip)

    145 unpack

    148 lambda

    152 iterable map, filter, zip iterator객체

    158 comprehension

    join, split, sort

     

    댓글

Designed by Tistory.