[Python] Pythonic Code For Coding Test

nang_zz·2022년 9월 14일
0
post-thumbnail

VSFe님의 github repository파이썬을 파이썬답게 강좌를 참고하여 작성하였습니다.


*(asterisk)

파이썬에서 *(asterisk)는 다음과 같은 상황에서 사용

  • 곱셈, 거듭제곱
  • List형 컨테이너를 반복해서 확장
  • 가변 인자
  • Unpacking

가변인자

  • 입력 받은 list에서 첫번째, 마지막 값만 얻고 싶은 경우
  • 입력 받은 list에서 첫번째, 마지막 값을 제외하고 싶은 경우

이런 경우 다음 예시와 같이 사용하면 된다.

_list = [1, 2, 3, 4, 5]
first_index, *rest, last_index = _list
print(rest)  # 2 3 4

위의 예시에서 rest에 사용한 것은 가변인자
인자의 갯수가 몇 개가 될지 확실하지 않은 경우에 사용.
first_index, last_index가 첫번째, 마지막 값을 가져가고, rest가 나머지를 가져간다.

Unpacking

Unpacking은 말그대로 풀어낸다는 뜻으로 list, tuple, set같은 컨테이너형 구조에서 모두 적용가능하다.

_list = [1, 2, 3, 4, 5]
print(_list) # [1, 2, 3, 4, 5]
print(*_list) # 1 2 3 4 5

그냥 _list를 출력하면 리스트 형태가 그대로 나오지만, *(asterisk)를 사용하여 unpacking하면 풀어서 출력된다.

💡 Packing

a = 1, 2, 3
print(a) # (1, 2, 3)

Packing은 말그대로 묶는다는 뜻으로, 하나의 변수에 여러 값을 할당하면 튜플로 묶인다.



List Comprehension

기본적인 List Comprehension은 파이썬 문법 부수기 포스트 참조

리스트 뿐만 아니라 tuple, set, dict도 만들 수 있다.

[심화 예시]

# 주어진 리스트를 그대로 담되, 15가 넘어가는 값은 15로 바꿔서 저장하기
_list = [i if i <= 15 else 15 for i in tmp]

# 값이 두개 들어있는 튜플을 받아 리스트를 생성하되, 튜플 내부의 값을 뒤집어서 저장하기
list_of_tuple = [(i, j) for i in range(100), for j in range(100, 0, -1)]
_list = [(j, i) for i, j in list_of_tuple]

# 두 개의 리스트를 합치되, 가능한 모든 조합을 저장하는 리스트를 만들기
x = [i for i in range(5)]
y = [i for i in range(5)]
_list = [(i, j) for i in x, for j in y]

앞 쪽에 붙는 if는 삼항 연산자의 if,
맨 끝에 붙는 if는 값을 for문의 if조건으로 값을 값을 넣을지, 뺄지 결정하는 조건



Set & Dictionary 잘 사용하기

Dictionary와 Set이 있다는 것은 알지만 어디에 사용하면 좋은지, 어떻게 해야 잘 사용할 수 있는지 알아보자

Dictionary와 Set은 Hash Table 구조를 띄고 있어 삽입, 삭제, 탐색 연산의 시간복잡도가 O(1)O(1)이다.

초보자들이 값을 찾기 위해 보통 list에서 in을 사용하는데 이 경우엔 순차적으로 탐색하게 되므로 데이터 양이 많아질수록 많은 시간이 소요됨.

이럴 땐 set을 사용하자.

set 사용

set을 사용하여 O(1)O(1)의 시간복잡도로 탐색 가능.

data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_data_set = set(data)

for i in range(10000):
    if i in _data_set:
        print(1)

set(집합)은 또한 같은 값이 들어올 수 없기에 다음과 같이 응용이 가능하다.

# 중복된 값을 포함하는 리스트에서 중복값 제거
duplicate_element = [21, 31, 65, 21, 58, 94, 13, 31, 58]
completed_list = list(set(duplicate_element)) # 21, 31, 65, 58, 94, 13

# 소문자로 바꾼후 중복된 원소들 제거
test_list = ['Test', 'test', 'TEST', 'tteesstt']
converted_list = list(set(map(lambda string: string.lower(), test_list))) # test, tteesstt

Dictionary

dictionary는 키와 쌍으로 이루어져있다.

fruit = ['apple', 'grape', 'orange']
price = [3200, 15200, 9800]
_dict = {}

for i in range(len(price)):
    _dict.append((fruit[i], price[i]))
    
 # {'apple' : 3200, 'grape' : 15200, 'orange' : 9000}

여기서 zip을 활용하면 더 쉽게 dictionary를 만들 수 있다.

zip

zip은 각 iterables의 요소들을 모으는 iterator를 만든다.

zip 함수에 서로 다른 길이의 리스트가 인자로 들어오는 경우 길이가 짧은 쪽까지만 이터레이션이 이루어진다.

fruit = ['apple', 'grape', 'orange']
price = [3200, 15200, 9800]

_dict = dict(zip(fruit, price))

 # {'apple' : 3200, 'grape' : 15200, 'orange' : 9000}

setdefault

딕셔너리에서 없는 값을 찾으려고 하면 오류가 난다.
이 때, setdefault를 사용하면 값이 있을 땐 해당 값을 리턴하고, 값이 없을 때는 두번째 인자로 넘겨준 값을 추가하고 추가한 값을 리턴해준다.

fruit = ['apple', 'grape']
price = [3200, 15200]
_dict = dict(zip(fruit, price))

print(_dict.setdefault('strawberry', 0)) # 0
# {'apple': 3200, 'grape': 15200, 'strawberry': 0}

defaultdict

매번 setdefault를 실행하는 데에 번거로울 때 defaultdict을 이용하면 setdefault를 암묵적으로 실행해준다.

from collections import defaultdict

movie_review = [('Clementine', 5), ('Parasite', 4.5), ('Clementine', 5)]

index = defaultdict(list)

for review in movie_review:
    index[review[0]].append(review[1]) 
# {'Clementine': [5, 5], 'Parasite': [4.5]}

print(index['Train to Busan']) # []
# {'Clementine': [5, 5], 'Parasite': [4.5], 'Train to Busan': []}


문자열 뒤집기

string = 'I am Hungry...'
print(string[::-1])
print("".join(reversed(string)))

첫 번째 방법은 모든 iterable한 데이터에서 사용 가능.
두 번째 방법은 역순으로 뒤집은 iterator 리턴하여 join이나 for i in ~ 구조 사용



기타

for, while문 에서의 else

이중 이상의 반복문에서 flag를 넣어 참/거짓 여부를 판단하여 중간에 break 하는 경우

[예제]
5개의 숫자를 차례로 곱해 나온 수가 제곱수면 found, 모든 수를 곱해도 제곱수가 나오지 않은 경우 not found 출력

import math

numbers = [int(input()) for _ in range(5)]
multiplied = 1
flag = True
for number in numbers:
    multiplied *= number
    if math.sqrt(multiplied) == int(math.sqrt(multiplied)):
        flag = False
        print('found')
        break
if flag:
        print('not found')
import math

numbers = [int(input()) for _ in range(5)]
multiplied = 1
for number in numbers:
    multiplied *= number
    if math.sqrt(multiplied) == int(math.sqrt(multiplied)):
        print('found')
        break
else:
    print('not found')

break로 반복문을 탈출하지 않았다면 else 구간으로 진입.

divmod

정수를 나눈 몫과 나머지를 구해야 할 경우
a//b, a%b를 사용할 수도 있지만 아주 큰 숫자를 다룰 때에는 divmod도 사용할 수 있다.

참고로 divmod 사용 시 tuple 형태로 return 되기 때문에 unpacking을 이용할 수 있다.

a = 7
b = 5
print(a//b, a%b)     # 1 2
print(*divmod(a,b))  # 1 2

10진법 진법 변환

n진수 → 10진수 변환 시 int(string, base) 사용

문자열 정렬(ljust, center, rjust)

  • 좌측 정렬 : ljust(width, [fillchar])
  • 가운데 정렬 : center(width, [fillchar])
  • 우측 정렬 : rjust(width, [fillchar])

fillchar 생략 시 공백으로 채워짐.

s = 'abc'
n = 7

s.ljust(n) # 좌측 정렬
s.center(n) # 가운데 정렬
s.rjust(n) # 우측 정렬

[출력]

abc    
  abc  
    abc

string 모듈(상수)

모든 소문자, 대문자, 대소문자, 숫자 가져오기

import string 

string.ascii_lowercase # 소문자 abcdefghijklmnopqrstuvwxyz
string.ascii_uppercase # 대문자 ABCDEFGHIJKLMNOPQRSTUVWXYZ
string.ascii_letters # 대소문자 모두 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
string.digits # 숫자 0123456789

가장 큰 수, inf

아주 큰 값을 할당 할 때, inf를 사용한다. inf는 어떤 숫자와 비교해도 무조건 크다고 판정된다.
-inf도 사용가능

파일 입출력 간단하게 하기

with - as 구문을 이용하면
1. 파일을 close 하지 않아도 된다: with - as 블록이 종료되면 파일이 자동 close
2. readlines가 EOF까지 읽으므로, while문 안에서 EOF 체크할 필요가 없다.

with open('myfile.txt') as file:
    for line in file.readlines():
        print(line.strip().split('\t'))
profile
블로그 이전했어요. fine-dev.site

0개의 댓글