Python

Python Cheat sheet

리버스레벨 2023. 6. 7. 12:28

Get started

파이썬을 파이썬답게!
파이썬에 사용을 조금 더 부드럽게 하기 위한 Cheat sheet
지속 업데이트 할 예정 (2022.07.10 ~ )

 

가독성이나 팀 코드 스타일에 따라 다를 수 있으니 유연하게 대처하고 사용하는 걸로 하자

아래의 코드는 pythonic하지 않음!!

def solution(li):
    answer = []
    for i in li:
        answer.append(len(i))
    return answer

이것이 파이썬이다.

(한줄 코딩이 파이써닉..?)

def solution(li):
    return list(map(len, li))

 

Unpacking

파이썬에서는 Asterisk(*) 를 매우 다양하게 사용하고 있다
곱셈 연산, 가변 인자 사용 등 여러 상황에서 사용하지만 여기서는 packing & unpacking의 예를 보겠다

list의 값들을 unpacking하여 풀어서 사용 가능


li = [1, 3, 5, 7, 9]

print(li)   # [1, 3, 5, 7, 9]
print(*li)  # 1 3 5 7 9

가변 인자로 넘겨줄 때 아주 간편하게 사용이 가능하다


from functools import reduce

li = [3, 6, 9, 12, 15]

def sum(*numbers):
    s = reduce(lambda x, y: x + y, numbers)
    return s

sum(*li) # 45

물론 dictionary도 가능 list, tuple과는 달리 **를 사용함

def dict_unpack(A, B):
    return A*B

C = {'A':2, 'B':2 }

dict_unpack(**C) # 4

음 간단하군...

cf) Dictionary review

user = {
    "name" : "jason",
    "email" : "junsu.pbear@kakao.com",
    "password" : None
}
def personal_info(**kwargs):
    for kw, arg in kwargs.items():
        print(kw, ': ', arg, sep='')
print(*user)  #  name email password
personal_info(**user)   # name: jason
                        # email: junsu.pbear@kakao.com
                        # password: None

단일로 unpacking을 할 경우에는 *var, = [...] 로 적어준다
*var,로 받는 인자의 경우에 일단 unpacking 된 다음에 변수에 할당되는 값들은 제외한 후 다시 packing

numbers = [1, 2, 3, 4, 5, 6]

*a, = numbers
# a = [1, 2, 3, 4, 5, 6]

*a, b = numbers
# a = [1, 2, 3, 4, 5]
# b = 6

a, *b, = numbers
# a = 1
# b = [2, 3, 4, 5, 6]

a, *b, c = numbers
# a = 1
# b = [2, 3, 4, 5]
# c = 6

 

몫과 나머지

몫과 나머지를 구해야 하는 상황
a,b를 input으로 공백으로 구분되게 받는다고 하면 기본 연산자를 사용하게 되면 아래와 같음

a, b = map(int, input().strip().split(' '))
print(a // b, end = ' ')
print(a % b, end = ' ')

But in Python...

a, b = map(int, input().strip().split(' '))
print(*divmod(a, b)) # unpacking

divmod() 함수를 사용하여 한 번에 구할 수 있다
그러나 모든 상황에서 사용하는 것이 좋은 방법은 아님

퍼포먼스의 경우에 작은 수를 다루게 되면 오히려 느릴 수 있음
적절한 상황에서 사용할 수 있도록 하자

 

진법 변환

5진법으로 적혀있는 문자열 10진법으로 변환하기

num = '3212'
base = 5

answer = 0
for idx, number in enumerate(num[::-1]):
    answer += int(number) * (base ** idx)

But in Python...

num = '3212' # 문자열이여야 함
base = 5     # 몇 진법인가
answer = int(num, base) # 432

10진법으로의 변환은 아주 자유로움

그렇다면 10진수에서의 변환은...?

# 결과값은 모두 string

print(bin(10)) #0b1010
print(oct(10)) #0o12
print(hex(10)) #0xa

# 앞에 2개의 값은 진법을 나타냄
print(hex(10)[2:]) #a

이건 그냥 만들어서 쓰자...

import string
tmp = string.digits+string.ascii_lowercase
def convert(num, base) :
    q, r = divmod(num, base)
    if q == 0 :
        return tmp[r] 
    else :
        return convert(q, base) + tmp[r]

 

sorted()

파이썬 기본 내장함수인 sort() 도 존재하지만 이 함수는 원본의 순서를 바꿈

list1 = [3, 2, 5, 1]
list2 = [i for i in list1] # 또는 copy.deepcopy를 사용
list2.sort()

요렇게 하면..?
sorted(iterable, /, *, key=None, reverse=False)

list1 = [3, 2, 5, 1]
list2 = sorted(list1)

새롭게 복사된 list에 정렬이 된다

여러개의 비교 요소도 tuple로 처리하여 우선 순위를 정해줄 수 있다

a = [(1, 2), (5, 1), (0, 1), (5, 2), (3, 0)]
e = sorted(a, key = lambda x : (x[0], -x[1])) # 마이너스를 붙이면 현재와 반대 정렬
# [(0, 1), (1, 2), (3, 0), (5, 2), (5, 1)]

 

zip()

zip(*iterables) 각 iterables의 요소들을 모은 iterator

mylist = [1, 2, 3]
new_list = [40, 50, 60]
for i in zip(mylist, new_list):
    print (i)

# (1, 40)
# (2, 50)
# (3, 60)  # tuple을 return

dicitonary도 생성 가능!

animals = ['cat', 'dog', 'lion']
sounds = ['meow', 'woof', 'roar']
answer = dict(zip(animals, sounds))
print(answer)  # {'cat': 'meow', 'dog': 'woof', 'lion': 'roar'}

2차원 배열 전치 행렬로 뒤집기도 가능!

mylist = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
new_list = list(map(list, zip(*mylist)))

index를 사용하지 않고 각 원소에 접근할 수 있다
But 서로 길이가 다른 iterator가 들어오게 되면 짧은 쪽까지만 iteration이 이뤄진다

def solution(mylist):
    answer = []
    for number1, number2 in zip(mylist, mylist[1:]):
        answer.append(abs(number1 - number2))
    return answer

if __name__ == '__main__':
    mylist = [83, 48, 13, 4, 71, 11]    
    print(solution(mylist))

길이가 긴 쪽을 조용히 잘라내는 것이 싫을 경우에는..?
itertools.zip_longest(*iterables, fillvalue=None)

from itertools import zip_longest 

x = [1, 2, 3]
y = [4, 5, 6,7]
zipped = zip_longest(x, y)
print(list(zipped)) # [(1, 4), (2, 5), (3, 6), (None, 7)]

zipped = zip_longest(x, y, fillvalue=0)
print(list(zipped)) # [(1, 4), (2, 5), (3, 6), (0, 7)]

 

map()

iterator의 요소를 지정된 함수로 처리해주는 함수

t1 = (3.14, 3.5, 22.6)
t2 = list(map(int, t1)) # [3, 3, 22]

여러가지로 활용이 가능해 보이니까 조금 더 신박한 사용 예 찾아보기

 

join()

join, split, strip, ljust, replace 등등 문자열 조작하는 함수는 자주 사용하니까...

split(sep=None, maxsplit=-1)

join(__iterable: Iterable[str]) -> str

li = ["6","6","6","6","6","6","6","6"]

s = ''.join(li) # 66666666
s2 = ' '.join(li) # 6 6 6 6 6 6 6 6

l = s.split() # ['66666666']
l2 = s2.split # ['6', '6', '6', '6', '6', '6', '6', '6']

 

product()

파이썬은 iterable한 객체가 너무 많음
itertools.product()

곱집합을 잘 만들어내는 것 가능!

from itertools import product

iterable1 = 'ABCD'
iterable2 = 'xy'

cartesian = list(map(''.join, list(product(iterable1, iterable2))))
# ['Ax', 'Ay', 'Bx', 'By', 'Cx', 'Cy', 'Dx', 'Dy']

 

cf) Itertools

조합, 순열

from itertools import combinations, permutations, combinations_with_replacement

pool = ['A', 'B', 'C']
print(list(map(''.join, permutations(pool)))) # 3개의 원소로 수열 만들기
print(list(map(''.join, permutations(pool, 2)))) # 2개의 원소로 수열 만들기
print(list(map(''.join, combinations(pool, 2)))) 
print(list(map(''.join, combinations_with_replacement(pool, 2))))

# ['ABC', 'ACB', 'BAC', 'BCA', 'CAB', 'CBA']
# ['AB', 'AC', 'BA', 'BC', 'CA', 'CB']
# ['AB', 'AC', 'BC']
# ['AA', 'AB', 'AC', 'BB', 'BC', 'CC']

 

Counter

어떤 원소 x가 주어진 시퀀스타입에 몇 번이나 나오는지 count
collections.Counter([iterable-or-mapping])

from collections import Counter

myList = [1, 2, 3, 4, 5, 6, 7, 8, 7, 9, 1, 2, 3, 3, 5, 2, 6, 8, 9, 0, 1, 1, 4, 7, 0]
answer = Counter(myList)

print(answer[1]) # = 4
print(answer[3])  # = 3
print(answer[100]) # = 0

sortedArr = Counter.most_common(answer) 
print(sortedArr) 
# [(1, 4), (2, 3), (3, 3), (7, 3), (4, 2), (5, 2), (6, 2), (8, 2), (9, 2), (0, 2)]

 

bisect

이진 탐색 (Binary Search)
오르차순 정렬된 리스트에서 특정한 값의 위치를 찾는 알고리즘

무조건 모듈을 사용하는 것은 좋지 않은 방법일수도...?

def bisect(a, x, lo=0, hi=None):
    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo + hi) // 2
        if a[mid] < x:
            lo = mid + 1
        else:
            hi = mid
    return lo

mylist = [1, 2, 3, 7, 9, 11, 33]
print(bisect(mylist, 3))

근데 파이썬은 못 참지..

from bisect import bisect

mylist = [1, 2, 3, 7, 9, 11, 33]
print(bisect(mylist, 3))

 

_str_()

class 내부의 인스턴스 출력 format을 설정이 가능하다.

class Coord(object):
    def __init__ (self, x, y):
        self.x, self.y = x, y
    def __str__ (self):
        return 'str method <<{}, {}>>'.format(self.x, self.y)

point = Coord(1, 2)
print(point) # str method <<1, 2>>

 

파일 시스템

with - as 구문은 파일 뿐만 아니라 socket이나 http 등에서도 사용 가능

with open('myfile.txt') as file:
    for line in file.readlines():
        print(line.strip().split('\t'))

 

EOF

계속 추가하긴 할텐데 뭔가 내가 코딩테스트에 사용할 거 위주로 정리하기 해야 할 것 같다.

오늘도 한 걸음!