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()
대신 sys.stdin.readline()
사용input()
과는 다르게 개행문자가 포함되어 입력된다. 개행문자는 rstrip()
메서드로 제거할 수 있다.print()
대신 sys.stdout.write()
사용print()
와는 다르게 문자열만 출력 가능하며 개행문자 없이 출력된다.print()
의 sep
, end
등의 인수를 활용할 수 없고 인수 언패킹 또한 불가능하기 때문에 이에 대해선 다른 방식으로 처리해야 한다." "
을 더하면 빈 칸을 넣고, 개행문자 "\n"
을 더하면 줄바꿈 한다.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)