{ }codelper

배우기 › Python

언어마다 다른 것 · 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)
stdin
3 1 4 1 5 9 2 6
hello world codes
stdout
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"처럼 부분 문자열을 찾아요.

언어별로 쓰는 법

Pythonf-문자열 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으로 두세요.

연습 문제