lambda args: expression
,
으로 구분하여 여러 개를 정의할 수 있다. if
, try
, for
, while
문과 같은 표현식이 아닌 문장(statement)은 쓸 수 없으며 람다 식이 너무 길면 가독성이 떨어지기 때문에 한 줄 정도의 간단한 코드만 쓰는 게 좋다.lambda x, y: x + y
map()
과 filter()
의 function
인수, sorted()
, sort()
, max()
, min()
의 key
인수 등이 있다.def
문을 사용하라고 권장한다.# 둘 다 같은 방식으로 작동하지만 식별자에 람다를 넣으면 람다를 사용하는 의미가 퇴색될 수 있으므로, 주의할 것.
my_func = lambda x, y: x + y
my_func(1, 2)
def my_func(x, y):
return x + y
my_func(1, 2)
my_dict = {"Z": 10000, "C": 500, "D": 100, "A": 200}
# sorted() 함수의 정렬 기준(key=)을 아이템의 값(item[1])으로 하여 정렬
# 이렇게 하면 딕셔너리의 값(value) 기준 오름차순으로 정렬된다.
dict(sorted(my_dict.items(), key=lambda item: item[1])) # {'D': 100, 'A': 200, 'C': 500, 'Z': 10000}
# 람다를 쓰지 않으면 이런식으로 써야한다.
def sort_by_value(item):
return item[1]
dict(sorted(my_dict.items(), key=sort_by_value))
# 단어 리스트를 고유한 문자의 수로 정렬하기
words = ["aaaa", "bbbb", "asdf", "fffooo", "barbar", "qwertyuiop"]
sorted(words, key=lambda word: len(set(word))) # ['aaaa', 'bbbb', 'fffooo', 'barbar', 'asdf', 'qwertyuiop']
x = 2
f = lambda y: x * y
x = 3
g = lambda y: x * y
# f(10)의 평가 시점에 변수 x가 갖는 값을 사용한다.
print(f(10)) # 따라서 20이 아니라 30 출력
print(g(10)) # 30 출력
# 기본값이 있는 인수 사용하기
x = 2
f = lambda y, x=x: x * y
x = 3
g = lambda y, x=x: x * y
print(f(10)) # 20 출력
print(g(10)) # 30 출력
print(f(10)) # 20 출력
map(function, iterable, ...)
a, b = map(int, input().split())
split()
을 써서 리스트로 만들고, 이 리스트의 모든 값을 int로 형변환하여 맵 객체를 반환한다. 마지막으로 맵 객체가 변수 a, b에 언패킹되면서 입력한 값이 저장된다.# 첫 줄에서 리스트의 총 개수를 입력받고 그 개수만큼의 요소를 포함하는 중첩된 리스트를 만드는 코드이다
# 리스트 컴프리헨션으로 여러 개의 input()을 쓰면 for 반복문의 input()부터 입력을 받는다
nested_list = [list(map(int, input().split())) for _ in range(int(input()))]
# 풀어쓴 코드
nested_list = []
for _ in range(int(input())):
input_list = list(map(int, input().split()))
nested_list.append(input_list)
# 입력받은 첫번째 정수 만큼의 크기를 가지는 리스트 만들기
num, *num_list = map(int, input().split()) # 첫번째 정수만 num에 저장되고, 나머지는 num_list에 패킹 된다
# 5 1 3 5 7 9 입력하면
# num_list은 [1, 3, 5, 7, 9]
arr = [1, 2, 3, 4]
print("".join(map(str, arr))) # 1234
zip(*iterables, strict=False)
for item in zip([1, 2, 3], ['sugar', 'spice', 'everything nice']):
print(item)
# 출력
(1, 'sugar')
(2, 'spice')
(3, 'everything nice')
keys = [1, 2, 3]
values = ["A", "B", "C"]
dict(zip(keys, values)) # {1: 'A', 2: 'B', 3: 'C'}
list(zip(range(3), ['fee', 'fi', 'fo', 'fum'])) # 'fum'은 무시됨: [(0, 'fee'), (1, 'fi'), (2, 'fo')]
strict=True
를 사용할 수 있다.list(zip(('a', 'b', 'c'), (1, 2, 3), strict=True))
[('a', 1), ('b', 2), ('c', 3)]
strict=True
인데 이터러블 간의 길이가 맞지 않는 경우, ValueError
가 발생한다.for item in zip(range(3), ['fee', 'fi', 'fo', 'fum'], strict=True):
print(item)
(0, 'fee')
(1, 'fi')
(2, 'fo')
Traceback (most recent call last):
...
ValueError: zip() argument 2 is longer than argument 1
strict=False
(기본값)이어도 zip()은 잘 작동하긴 하지만, 서로 다른 길이의 이터러블들을 zip으로 묶으면서 나오는 버그들을 알 수 없어지므로 길이가 엄격하게 맞아야 하는 상황에서는 strict=True
를 이용하는게 좋다.itertools.zip_longest()
를 사용하여 더 짧은 이터러블에 상수값을 추가함으로써 이터러블 간의 길이를 맞출 수 있다.import itertools
a = [1, 2, 3]
b = [4]
list(itertools.zip_longest(a, b, fillvalue=0)) # [(1, 4), (2, 0), (3, 0)]
a = [1, 2, 3]
print(list(zip(a))) # [(1,), (2,), (3,)]
zip() # <zip at 0x2832c7dd280>
print(list(zip())) # []
zip(*[iter(s)]*n, strict=True)
를 사용하여 이터러블 객체 s에서 n개의 요소가 담긴 튜플들의 그룹으로 묶을 수 있다.s = [1, 2, 3, 4]
n = 2
list(zip(*[iter(s)]*n, strict=True)) # [(1, 2), (3, 4)]
a = iter([1, 2, 3, 4])
print(list(zip(a, a))) # [(1, 2), (3, 4)]
*
를 활용하여 unzip 할 수 있다. foo = (1, 2, 3)
bar = ("A", "B", "C")
baz = list(zip(foo, bar))
print(baz) # [(1, 'A'), (2, 'B'), (3, 'C')]
spam, eggs = zip(*baz)
print(spam) # (1, 2, 3)
print(eggs) # ('A', 'B', 'C')
x = [1, 2, 3]
y = [4, 5, 6]
list(zip(x, y)) # [(1, 4), (2, 5), (3, 6)]
x2, y2 = zip(*zip(x, y))
x == list(x2) # True
y == list(y2) # True
filter(function, iterable)
filter()
는 주어진 조건함수(function)에 따라 iterable의 요소들을 필터링 하는 파이썬 내장함수이다.None
을 넣을 수 있다.None
이면, 항등함수가 가정된다. 즉, iterable에서 False
한 요소가 모두 제거된 이터레이터가 반환된다.filter(None, iterable)
은 제너레이터 표현식 (item for item in iterable if item)
와 같다.None
이 아니면 (item for item in iterable if function(item))
와 같다. # 주어진 리스트에서 False한 요소를 뺀 리스트 만들기
items = [1, "", " ", 2, None, False, 3]
list(filter(None, items)) # [1, ' ', 2, 3]
list(item for item in items if item) # [1, ' ', 2, 3]
# 주어진 문자열 리스트에서 알파벳 문자만 골라내기
items = ["1", "A", "2", "B"]
list(filter(str.isalpha, items)) # ['A', 'B']
list(item for item in items if item.isalpha()) # ['A', 'B']
# 주어진 정수 리스트에서 짝수만 골라내기
items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list(filter(lambda x: x % 2 == 0, items)) # [2, 4, 6, 8, 10]
functools.reduce(function, iterable[, initializer])
functools.reduce(집계함수, 순회 가능한 데이터[, 초기값])
reduce()
는 빌트인 함수가 아니며 functools
모듈에 있으므로 임포트 해줘야 쓸 수 있다.reduce
는 집계함수 function을 iterable에 반복적으로 적용하여 그 결과로 하나의 값을 반환하는 함수이다.reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])
는 이 수식((((1+2)+3)+4)+5)
과 같다.reduce()
는 두 개의 요소로만 연산을 하기 때문에 function에 인수를 3개 이상 입력하는 함수를 넣으면 인수가 부족하다는 에러(TypeError
)가 발생한다.initializer
) 인수를 쓰면 초기값이 연산의 맨 앞에 배치되며, iterable 인수가 비어 있으면 기본값으로 사용된다. 초기값이 없고 이터러블 항목이 하나만 있으면 첫 번째 항목이 반환된다.from functools import reduce
add = lambda x, y: x + y
reduce(add, [1, 2, 3, 4]) # 10
reduce(add, [1, 2, 3, 4], 100) # initializer가 100이라 110 반환
reduce(add, [1]) # 1
reduce(add, [], 100) # 100
def add_digits(num: int) -> int:
'''
자리수가 하나만 남을 때까지 자연수의 모든 자리수를 더한 값을 출력
'''
print(num)
if num < 10:
return num
else:
# int형의 num 변수는 이터러블이 아니므로 문자열로 변환
add_digits(reduce(lambda x, y: int(x) + int(y), str(num)))
add_digits(13567)
# 출력
# 13567
# 22
# 4
input()
, print()
를 써도 문제가 없지만 입력 크기가 크거나 시간 제한이 짧으면 코드에 문제가 없어도 시간초과가 되어 통과가 안되는 경우가 있다. (백준 15552번, 1927번, 10845번 등)sys
모듈의 표준입출력 관련 함수들을 활용하는 것이다. 이 함수들은 input()
과 print()
보다 저수준에서 동작하며 비교적 단순하게 데이터를 처리하기 때문에 더 빠르게 입출력할 수 있다.input()
대신 sys.stdin.readline()
사용input()
과는 다르게 개행문자가 포함된 문자열을 반환한다. 개행문자는 문자열의 rstrip()
메서드로 제거할 수 있다.print()
대신 sys.stdout.write()
사용print()
와는 다르게 오직 문자열만 출력 가능하며 개행문자 없이 출력된다." "
을 더하면 빈 칸을 넣고, 개행문자 "\n"
을 더하면 줄바꿈 한다.print()
의 sep
, end
등의 인수를 활용할 수 없고 인수 언패킹 또한 불가능하기 때문에 이에 대해선 다른 방식으로 처리해야 한다.sys.stdout.write("\n".join(words_list))
이런식으로 리스트의 모든 내용을 한 줄씩 출력할 수 있다.# 백준 15552번
import sys
num = int(sys.stdin.readline().rstrip())
ret = [sum(map(int, sys.stdin.readline().split())) for _ in range(num)]
for v in ret:
sys.stdout.write(str(v) + "\n")
# 내장 입출력 함수 input(), print() 대체하기
from sys import stdin, stdout
input = stdin.readline
print = stdout.write
입력은 여러 개의 테스트 케이스로 이루어져 있다.
이런식으로 쓰여있는 문제는 입력 크기를 알 수 없다고 가정하고 풀어야 한다.try
와 except
문으로 EOFError
가 나오면 반복문을 종료하는 코드로 만들면 된다.while True:
try:
a, b = map(int, input().split())
print(a + b)
except EOFError:
break
sys.getrecursionlimit()
로 현재의 재귀호출 제한을 알 수 있고sys.setrecursionlimit(limit)
로 재귀호출 제한을 재설정할 수 있다.RecursionError
가 발생하므로 다음과 같이 재귀호출 제한을 늘려줘야 한다.import sys
sys.setrecursionlimit(10**6)