언어마다 다른 것 · 40
파이썬다운 코드
내포, 간격 있는 자르기, 풀어 넣기, enumerate·zip, in, f-문자열, 그리고 세 가지 함정.
이 단원은 Python에서 배워요.
다른 언어는 같은 일을 반복문이나 라이브러리 메서드로 해요(JavaScript map·filter, Java 스트림, C# LINQ, C·C++·크레이콘은 반복문과 넣기).
파이썬에는 반복문 여러 줄을 한 줄로 줄여 주는 짧은 꼴이 많아요.
아래 예제는 내포·자르기·풀어 넣기·enumerate·zip·f-문자열을 차례로 써 보고, 마지막에 오류 없이 엉뚱한 답을 내는 함정 두 가지를 보여 줘요.
nums = list(map(int, input().split()))words = input().split() odd_squares = [x * x for x in nums if x % 2 == 1]print(*odd_squares)print({x % 3 for x in nums})print({w: len(w) for w in words}) print(*nums[::-1])print(*nums[1:6:2])print(words[0][::-1]) first, *rest = numsa, b = first, rest[-1]a, b = b, aprint(a, b, len(rest)) for i, w in enumerate(words, start=1): print(f"{i}. {w:<6}|")print(*(f"{w}={n}" for w, n in zip(words, nums)))print(9 in nums, "lo" in words[0]) gen = (x for x in nums)print(sum(gen), sum(gen)) grid = [[0] * 3] * 2grid[0][0] = 1print(grid)grid = [[0] * 3 for _ in range(2)]grid[0][0] = 1print(grid)3 1 4 1 5 9 2 6 hello world codes
9 1 1 25 81
{0, 1, 2}
{'hello': 5, 'world': 5, 'codes': 5}
6 2 9 5 1 4 1 3
1 1 9
olleh
6 3 7
1. hello |
2. world |
3. codes |
hello=3 world=1 codes=4
True True
31 0
[[1, 0, 0], [1, 0, 0]]
[[1, 0, 0], [0, 0, 0]]
핵심
- 내포(comprehension)는 반복문 한 줄로 새 목록을 만들어요.
[x * x for x in nums if x % 2 == 1]은 "홀수만 골라 제곱한 목록"이고, 빈 목록에append하는 네 줄짜리 반복문이 이 한 줄이 돼요. - 괄호만 바꾸면 같은 모양으로 집합
{x % 3 for x in nums}, 사전{w: len(w) for w in words}도 만들어요. - 자르기
a[시작:끝:간격]은 끝이 들어가지 않고, 빠진 칸은 처음·끝·1로 채워요.nums[1:6:2]는 1·3·5번,nums[::-1]은 뒤집은 새 목록,"hello"[::-1]은"olleh"예요. - 범위를 넘는 자르기는 오류가 아니라 있는 데까지만 줘요(
nums[5:100]).
음수 번호는 뒤에서부터라a[-1]이 마지막이에요. - 풀어 넣기:
a, b = b, a는 임시 변수 없이 맞바꾸고,first, *rest = nums는 첫 값과 나머지 목록으로 나눠요.
번호는enumerate(words, start=1), 두 목록을 나란히 돌 때는zip(words, nums)(짧은 쪽에서 멈춰요)로 돌아요. in은 들어 있는지 물어요.
목록은 앞에서부터 하나씩 찾아 느리고, 집합·사전은 거의 바로 찾아요.
문자열에서는"lo" in "hello"처럼 부분 문자열을 찾아요.
언어별로 쓰는 법
| Python | f-문자열 f"{i}. {w:<6}|"은 중괄호 안에 식, : 뒤에 모양(<6 왼쪽 맞춤 6칸, .2f 소수 둘째 자리).f"{x=}"는 x=3처럼 이름까지 찍어 줘서 디버깅에 편해요.range(len(...))로 번호를 돌리는 건 드물고, 간격 있는 자르기와 [::-1]은 파이썬에만 있는 짧은 꼴이에요 |
|---|
자주 하는 실수
기본값에 []을 뒀어요
def add(x, bucket=[]):
bucket.append(x)
return bucket
add(1); print(add(2))→ [1, 2] — []는 함수를 만들 때 한 번만 만들어져서 호출마다 같은 목록을 써요
bucket=None으로 두고 함수 안에서 if bucket is None: bucket = []로 새로 만들어요.
생성기를 두 번 썼어요
gen = (x for x in nums)
print(sum(gen), sum(gen))→ 31 0 — 소괄호 ( )는 목록이 아니라 한 번 쓰면 비는 생성기예요
두 번 쓸 거면 대괄호 [ ]로 목록을 만들어요.
[[0] * 3] * 2로 2차원 목록을 만들었어요
grid = [[0] * 3] * 2
grid[0][0] = 1
print(grid)→ [[1, 0, 0], [1, 0, 0]] — 바깥 * 2는 안쪽 목록을 복사하지 않고 같은 목록을 두 번 담아요
[[0] * 3 for _ in range(2)]처럼 내포로 줄마다 새로 만들어요([0] * 3처럼 수를 곱하는 건 괜찮아요).
언어마다 다른 점
곱하기(
목록을 여러 개 원하면 내포로, 기본값은
곱하기(
* m)로 만든 2차원 목록과 =[] 기본값은 오류 없이 같은 목록을 함께 써서 엉뚱한 곳이 바뀌어요.목록을 여러 개 원하면 내포로, 기본값은
None으로 두세요.