학습 자료

먼저 보는 문법 한 장 — 이 시리즈에 나오는 것만


Article

이 시리즈는 파이썬을 처음부터 가르치지 않는다. 문서를 자르고 검색하는 데 실제로 쓰는 것만 다룬다.

여기 모아둔 것이 그 전부다. 클래스도, 데코레이터도, async 도 나오지 않는다. 한 번 훑고 시작하면 되고, 막히면 이 페이지로 돌아오면 된다.

여섯 가지면 된다
  1. 문자열 자르기문서를 조각으로
  2. f-string값을 문장에 넣기
  3. 리스트 · 딕셔너리조각과 검색 결과를 담기
  4. 함수같은 일을 한 곳에
  5. 반복가장 많이 쓴다

준비 — 실습 폴더를 만든다

이 시리즈의 코드는 전부 파일로 저장해서 돌린다. 코드 블록 하나가 파일 하나다. 블록 위에 파일명이 적혀 있으니 그 이름으로 만들고, 복사 버튼을 눌러 통째로 붙여넣으면 그대로 실행된다.

한 번만 해두면 되는 준비
  1. 01

    바탕화면에 ai-course 폴더를 만든다

    이 시리즈에서 만드는 파일을 전부 여기에 넣는다. 이름은 소문자·영문으로 둔다.

  2. 02

    VS Code 로 그 폴더를 연다

    「파일 → 폴더 열기」로 `ai-course` 폴더 자체를 연다. 파일 하나만 여는 것과 다르다. 폴더를 열어야 터미널이 그 위치에서 시작한다.

  3. 03

    터미널을 켠다

    Ctrl + ` `` (숫자 1 왼쪽의 물결 키). 메뉴로는 「터미널 → 새 터미널」이다.

  4. 04

    터미널에 뜬 경로가 ai-course 로 끝나는지 확인한다

    여기가 어긋나면 파일을 만들어도 못 찾는다. 앞으로 뭔가 안 될 때 제일 먼저 볼 자리다.

첫 파일을 만들어 확인한다. 파일 이름은 코드 블록 위에 적힌 그대로 쓴다.

ai-course/01_실행확인.py
# 이 줄은 주석이다. 파이썬이 읽지 않고 사람만 본다.
# print 는 괄호 안의 것을 화면에 찍는다.
print("파이썬이 돌아간다")
print(1 + 1)

저장한 뒤 터미널에 이렇게 친다.

python 01_실행확인.py
터미널
  • 파이썬이 돌아간다
  • 2

이게 나오면 준비가 끝났다. 앞으로 모든 실습이 파일 만들기 → 붙여넣기 → python 파일명.py 세 단계다.


1. 문자열 — 글자를 한 줄로 세운 것

ai-course/02_문자열.py
# = 는 "같다"가 아니라 "왼쪽 이름에 오른쪽 값을 넣는다"는 뜻이다
s = "백엔드 개발자는 서버를 다룬다"

# len 은 length(길이). 글자 수를 센다. 공백도 한 글자다
print(len(s))

# 번호로 글자 하나를 꺼낸다. 0부터 센다
print(s[0])          # 0번째 = 첫 글자
print(s[-1])         # 음수는 뒤에서부터. -1 이 마지막

# 콜론(:)을 넣으면 구간이 나온다. 이게 "자르기"다
print(s[0:3])        # 0번부터 3번 "앞"까지 - 끝 번호는 포함되지 않는다
print(s[:3])         # 시작을 비우면 처음부터. 위와 같다
print(s[8:])         # 끝을 비우면 끝까지
print(s[8:9999])     # 길이를 넘겨도 에러가 아니다. 있는 만큼만 준다
터미널
  • 16
  • 백
  • 다
  • 백엔드
  • 백엔드
  • 서버를 다룬다
  • 서버를 다룬다

len(s) 가 16이다. 공백 두 개까지 세기 때문이다. 그리고 s[8:] 앞에 빈칸이 하나 보이는데, 8번 글자가 공백이라 그렇다.


2. f-string — 문장 안에 값 넣기

따옴표 앞에 f 를 붙이면 중괄호 안이 값으로 바뀐다.

ai-course/03_f스트링.py
name = "백엔드"
count = 3

# 따옴표 앞에 f 를 붙이면 중괄호 안이 값으로 바뀐다
print(f"{name} 개발자 {count}명")

# 중괄호 안에서는 계산도 되고 함수도 부를 수 있다
print(f"{count + 1}")           # 계산
print(f"{len(name)}")           # 함수 호출
print(f"{3.14159:.2f}")         # 콜론 뒤는 "어떻게 보여줄지"
print(f"[{count:3d}]")          # 정수를 3칸에 오른쪽 맞춤
print(f"[{name:6s}]")           # 문자열을 6칸에 왼쪽 맞춤
터미널
  • 백엔드 개발자 3명
  • 4
  • 3
  • 3.14
  • [ 3]
  • [백엔드 ]

[ 3] 은 앞에 빈칸 두 개, [백엔드 ] 는 뒤에 빈칸 세 개다. 숫자는 오른쪽, 글자는 왼쪽으로 맞추는 것이 기본값이다. 표를 만들 때 줄이 맞아 보이는 이유가 이것이다.

자주 쓰는 표시 방식
쓰는 법뜻예
{x}값 그대로3
{x:.2f}소수점 둘째 자리까지3.14
{x:3d}정수를 3칸에 오른쪽 맞춤 3
{x:6s}문자열을 6칸에 왼쪽 맞춤백엔드
{x[:30]}안에서 슬라이싱앞 30글자

3. 리스트 — 값을 순서대로 담는 상자

대괄호로 만든다. 문자열처럼 번호로 꺼내고, 콜론으로 자른다.

ai-course/04_리스트.py
# 대괄호로 만든다. 문자열처럼 번호로 꺼내고 콜론으로 자른다
jobs = ["백엔드", "프론트엔드", "데이터"]

print(len(jobs))     # 문자열에서는 글자 수, 리스트에서는 항목 수
print(jobs[0])       # 0번이 첫 항목인 것도 문자열과 같다
print(jobs[-1])      # 뒤에서 첫 항목
print(jobs[:2])      # 앞의 두 개

# 끝에 하나 붙일 때는 .append() 를 쓴다
jobs.append("기획")   # 점(.)은 "이 리스트에게 시키는 일"이라는 표시다
print(jobs)
터미널
  • 3
  • 백엔드
  • 데이터
  • ['백엔드', '프론트엔드']
  • ['백엔드', '프론트엔드', '데이터', '기획']

리스트를 통째로 찍으면 대괄호와 따옴표가 그대로 보인다. 항목 하나를 찍을 때는 따옴표가 없고, 리스트째 찍을 때는 붙는다. 파이썬이 「이건 문자열이다」를 표시해주는 것이라 생각하면 된다.


4. 딕셔너리 — 이름표를 붙여 담는 상자

중괄호로 만들고 이름과 값을 짝지어 담는다. 리스트가 번호로 꺼낸다면 이쪽은 이름으로 꺼낸다.

ai-course/05_딕셔너리.py
# 중괄호로 만들고 이름과 값을 짝지어 담는다
job = {"name": "백엔드", "years": 3}

print(job["name"])           # 대괄호에 번호 대신 이름을 넣는다

job["tool"] = "파이썬"        # 없는 이름에 넣으면 새로 생긴다
print(job)

# 없는 이름을 꺼내면 KeyError 가 난다. get 은 대신 None 을 준다
print(job.get("salary"))
터미널
  • 백엔드
  • {'name': '백엔드', 'years': 3, 'tool': '파이썬'}
  • None

마지막 None 은 「그런 이름이 없다」는 뜻이다. job["salary"] 라고 대괄호로 꺼냈다면 KeyError 로 프로그램이 멈췄을 것이다. .get() 은 없어도 멈추지 않는다.

언제 무엇을 쓰나

리스트

["백엔드", "프론트엔드"]

  • 같은 종류가 여러 개일 때
  • 순서가 있다
  • 조각 목록 · 검색 결과 목록

딕셔너리

{"name": ..., "score": ...}

  • 한 덩어리에 여러 정보가 붙을 때
  • 이름으로 꺼낸다
  • 조각 하나 + 점수 + 출처

5. 함수 — 같은 일을 이름 붙여 한 곳에

ai-course/06_함수.py
# def       "지금부터 함수를 만든다"
# greet     내가 붙인 이름. 앞으로 이 이름으로 부른다
# (name, title="개발자")
#           밖에서 받을 값. title 은 안 주면 "개발자"를 쓴다(기본값)
# 끝의 콜론  "아래 들여쓴 줄이 이 함수의 몸통"이라는 표시
def greet(name, title="개발자"):
    return f"{name} {title}"        # return 은 결과를 함수 밖으로 내보낸다


print(greet("김철수"))                # title 을 안 줬으니 기본값
print(greet("김철수", "기획자"))       # 줬으니 그걸 쓴다


# 일부러 return 을 뺀 함수
def no_return(x):
    x + 1               # 계산만 하고 안 내보낸다


print(no_return(1))     # 에러가 아니라 None 이 나온다
터미널
  • 김철수 개발자
  • 김철수 기획자
  • None
ai-course/07_함수_에러.py
def no_return(x):
    x + 1               # return 이 없다


# None 을 리스트인 줄 알고 len 을 씌우면 여기서 터진다
print(len(no_return(1)))
터미널
  • Traceback (most recent call last):
  • File "...\ai-course\07_함수_에러.py", line 6, in <module>
  • print(len(no_return(1)))
  • ~~~^^^^^^^^^^^^^^
  • TypeError: object of type 'NoneType' has no len()

에러는 마지막 줄부터 읽는다. 위쪽은 어디를 거쳐 왔는지의 경로이고, 원인은 맨 아래에 있다. ~~~^^^ 표시는 그 줄에서 정확히 어느 부분이 터졌는지 짚어준다.

그리고 line 6 은 터진 자리지 원인이 있는 자리가 아니다. 진짜 원인은 2번 줄, return 이 없다는 것이다. 이 어긋남이 초보자를 가장 오래 붙잡는다.

기본값이 있는 인자는 반드시 뒤에 온다. def f(a, b=1) 은 되고 def f(a=1, b) 는 에러다. 하나만 주고 불렀을 때 어느 자리인지 알 수 없기 때문이다.


6. 반복 — 가장 많이 쓴다

여기가 제일 중요하다. 앞으로 쓰는 코드의 절반이 반복이다.

① for 와 enumerate

ai-course/08_반복.py
jobs = ["백엔드", "프론트엔드", "데이터", "기획"]

# for A in B:  "B 에서 하나씩 꺼내 A 에 넣고, 아래 줄을 반복하라"
for j in jobs:
    print(j)            # 앞의 공백 4칸이 "이 줄은 for 안쪽"이라는 표시다

print("---")

# enumerate 는 번호와 값을 짝지어 준다. 그래서 받는 이름도 두 개
for i, j in enumerate(jobs):
    print(i, j)

print("---")

# 번호가 0부터라 사람이 세는 것과 어긋난다. start=1 하나면 해결된다
for i, j in enumerate(jobs, start=1):
    print(i, j)
터미널
  • 백엔드
  • 프론트엔드
  • 데이터
  • 기획
  • ---
  • 0 백엔드
  • 1 프론트엔드
  • 2 데이터
  • 3 기획
  • ---
  • 1 백엔드
  • 2 프론트엔드
  • 3 데이터
  • 4 기획

print("---") 는 결과를 눈으로 나누려고 넣은 것이다. 한 파일에서 여러 가지를 찍을 때 이렇게 구분선을 두면 어디까지가 무엇인지 바로 보인다.

② range — 숫자를 차례로 만든다

목록이 없고 숫자만 필요할 때 쓴다. 문서를 일정한 간격으로 자를 때가 그렇다.

ai-course/09_range.py
# 목록이 없고 숫자만 필요할 때 쓴다
print(list(range(3)))            # 0부터 3 "앞"까지
print(list(range(0, 10, 3)))     # 0부터 10 앞까지 3씩 건너뛰며

# range 와 슬라이싱은 끝 번호를 안 넣는 규칙이 같다. 그래서 맞물린다
text = "가나다라마바사아자차카타파하"
for start in range(0, len(text), 5):
    print(start, text[start:start + 5])
터미널
  • [0, 1, 2]
  • [0, 3, 6, 9]
  • 0 가나다라마
  • 5 바사아자차
  • 10 카타파하

이 여섯 줄이 다음 강의의 전부다. 문서를 일정 간격으로 자르는 일이 정확히 이 모양이다. 마지막 조각이 5글자가 안 되는 것도 그대로 나온다 — text[10:15] 인데 글자가 14개까지밖에 없어서 있는 만큼만 나왔다.

range 와 슬라이싱이 맞물린다

for start in range(0, len(text), 5):

start = 0
text[0:5]
0~4번
start = 5
text[5:10]
5~9번 — 겹치지 않는다
start = 10
text[10:15]
14번까지밖에 없어 4글자

③ 딕셔너리 반복 — .items() 를 잊지 않는다

ai-course/10_딕셔너리_반복.py
job = {"name": "백엔드", "years": 3, "tool": "파이썬"}

for k in job:               # 그냥 돌면 이름만 나온다
    print(k)

print("---")

for k, v in job.items():    # .items() 를 붙여야 이름과 값을 짝으로 준다
    print(k, "=", v)
터미널
  • name
  • years
  • tool
  • ---
  • name = 백엔드
  • years = 3
  • tool = 파이썬

위쪽은 이름만 나왔다. 값이 안 나온다고 딕셔너리가 비었다고 오해하기 쉬운 자리다. .items() 하나로 해결된다.

④ 모아 담기와 컴프리헨션

반복은 화면에 찍으려고 도는 게 아니라 결과를 모으려고 돈다.

ai-course/11_모아담기.py
jobs = ["백엔드", "프론트엔드", "데이터", "기획"]

# 반복은 화면에 찍으려고 도는 게 아니라 결과를 모으려고 돈다
result = []                 # 빈 리스트를 먼저 만들고
for j in jobs:
    result.append(len(j))   # 하나씩 쌓는다

print(result)

# 위 세 줄을 한 줄로 쓴 것이 컴프리헨션이다
# [ len(j)      for j in jobs ]
#   담을 것       어디서 꺼내나
print([len(j) for j in jobs])

# 뒤에 if 를 붙이면 걸러진다
print([j for j in jobs if len(j) >= 4])

# 담는 것이 딕셔너리여도 된다
print([{"name": j} for j in jobs[:2]])
터미널
  • [3, 5, 3, 2]
  • [3, 5, 3, 2]
  • ['프론트엔드']
  • [{'name': '백엔드'}, {'name': '프론트엔드'}]

첫 줄과 둘째 줄이 같다. 반복문 세 줄과 컴프리헨션 한 줄이 정확히 같은 일을 한다는 뜻이다. 컴프리헨션은 새 기능이 아니라 자주 쓰는 반복문의 줄임말이다.

같은 일, 두 가지 표기

반복문으로

세 줄

  • result = []
  • for j in jobs:
  • result.append(len(j))

컴프리헨션으로

한 줄

  • [len(j) for j in jobs]
  • 「담을 것」이 앞, 「어디서」가 뒤
  • 대괄호라 결과가 리스트인 게 바로 보인다

7. 판단 — 참인지 묻기

ai-course/12_판단.py
s = "백엔드 개발자는 서버를 다룬다"

print("서버" in s)       # in 은 "안에 있나"를 묻는다
print("디자인" in s)
print(3 == 3)            # == 는 "같은가". 값을 넣는 = 와 다르다

# 빈 것은 거짓이다. 이 성질을 자주 쓴다
print(not [])            # 빈 리스트
print(not "")            # 빈 문자열

paths = []
if not paths:
    print("찾은 게 없다")
터미널
  • True
  • False
  • True
  • True
  • True
  • 찾은 게 없다

8. 자주 만나는 에러 여섯 가지

이 여섯이 대부분이다
화면에 뜨는 것무슨 뜻어디를 보나
IndexError: list index out of range없는 번호를 꺼냈다jobs[99] — 길이를 넘었다
KeyError: '없는키'없는 이름을 꺼냈다딕셔너리 이름 오타
TypeError: ... 'NoneType' has no len()None 을 리스트처럼 썼다함수에 `return` 이 빠졌다
TypeError: can only concatenate str글자와 숫자를 더했다"3" + 3 — f-string 을 쓴다
IndentationError들여쓰기가 안 맞는다for · def 다음 줄 공백 4칸
NameError: name 'x' is not defined없는 이름을 썼다오타이거나, 다른 파일에서 만든 것

한 장 요약

이 시리즈에 나오는 문법 전부
쓰는 법하는 일
print(x)화면에 보여준다. 이게 없으면 아무것도 안 나온다
len(x)문자열이면 글자 수, 리스트면 항목 수
s[0] · s[-1]번호로 하나 꺼내기. 0부터, 음수는 뒤에서
s[0:3] · s[:3] · s[3:]구간 꺼내기. 끝 번호는 안 들어간다
f"{x}" · {x:.2f} · {x:3d}문장에 값 넣기와 보여줄 방식
[a, b, c]리스트 — 같은 종류 여럿
리스트.append(x)끝에 하나 붙이기
{"이름": 값} · d["이름"]딕셔너리 — 한 덩어리에 여러 정보
d.get("이름")없으면 에러 대신 None
def f(a, b=기본값): · return함수 만들기. 기본값은 뒤쪽에만
for x in 목록:하나씩 꺼내 반복
enumerate(목록, start=1)번호와 값을 같이
range(0, n, 간격)숫자를 차례로. 끝은 안 들어간다
d.items()딕셔너리를 이름·값 짝으로
[f(x) for x in 목록]컴프리헨션 — 반복문 한 줄
[x for x in 목록 if 조건]거르기
x in y · == · not x판단하기. 빈 것은 거짓

여기 없는 것은 이 시리즈에 나오지 않는다. 클래스, 데코레이터, 제너레이터, async — 전부 필요할 때 배우면 된다.

스스로 해보기

확인 문제 셋
  1. 01

    내 이름으로 문자열을 만들어 앞 두 글자를 꺼낸다

    ai-course/13_연습1.py 로 만들어 돌린다. 슬라이싱이 손에 익는 게 이 시리즈에서 제일 많이 쓰인다.

    me = "내 이름을 여기"
    print(me[:2])
  2. 02

    좋아하는 것 세 개를 리스트로 만들고 길이를 컴프리헨션으로 잰다

    ai-course/14_연습2.py. 반복문 세 줄로도 해보고 한 줄로도 해서 같은 결과가 나오는지 확인한다.

    likes = ["...", "...", "..."]
    print([len(x) for x in likes])
  3. 03

    함수를 하나 만들되 일부러 return 을 빼본다

    ai-course/15_연습3.py. 부르면 무엇이 나오나. 거기에 len() 을 씌우면 무슨 에러가 나나. 이 실수를 미리 해두면 나중에 훨씬 빨리 알아챈다.

1번 — 앞 두 글자 꺼내기충분히 고민해본 뒤 꼭 필요한 경우에만 열어보세요

me[:2] 는 me[0:2] 와 같다. 시작을 비우면 처음부터라는 뜻이다.

끝 번호 2는 들어가지 않는다. 0번과 1번, 두 글자다.

me = "김철수"

print(me[:2])        # 앞 두 글자
print(me[-1])        # 마지막 한 글자
print(me[1:])        # 두 번째부터 끝까지

차례로 김철 · 수 · 철수 가 나온다.

print 로 찍었으니 따옴표가 안 보인다. 대화형 화면에서 값만 쳤다면 '김철' 처럼 따옴표까지 보였을 것이다.

2번 — 컴프리헨션으로 길이 재기충분히 고민해본 뒤 꼭 필요한 경우에만 열어보세요

반복문 세 줄과 컴프리헨션 한 줄이 똑같은 결과를 낸다. 둘 다 돌려서 확인하는 것이 이 문제의 목적이다.

likes = ["영화", "산책", "커피"]

# 반복문으로 - 빈 리스트를 만들고 하나씩 쌓는다
result = []
for x in likes:
    result.append(len(x))
print(result)                    # [2, 2, 2]

# 컴프리헨션으로 - 같은 일을 한 줄에
print([len(x) for x in likes])   # [2, 2, 2]

두 줄이 같은 값이면 성공이다. 컴프리헨션은 새 기능이 아니라 같은 반복문을 짧게 쓴 것이다.

3번 — return 을 빼면충분히 고민해본 뒤 꼭 필요한 경우에만 열어보세요

부르면 에러가 안 난다. 파이썬이 조용히 None 을 돌려주기 때문이다.

그걸 리스트인 줄 알고 len() 을 씌우면 그제서야 터진다. 에러가 난 자리와 원인이 있는 자리가 다르다.

def no_return(x):
    x + 1               # 계산만 하고 밖으로 안 내보낸다


print(no_return(1))     # None 이 나온다
print(len(no_return(1)))  # 여기서 터진다

TypeError: object of type 'NoneType' has no len()

이 에러를 보면 「어딘가에 return 이 빠졌다」를 먼저 의심하면 된다.

정리하면

문자열을 자르고, 값을 문장에 넣고, 리스트와 딕셔너리에 담고, 함수로 묶고, 반복으로 처리한다. 다섯 가지가 전부다.

그중 반복이 가장 많이 나온다. 문서를 조각내는 것도, 조각마다 점수를 매기는 것도, 상위 몇 개를 뽑는 것도 전부 반복이다.

그리고 실습 방식이 하나 정해졌다. 파일을 만들고, 붙여넣고, python 파일명.py 로 돌린다. 앞으로 나오는 모든 코드 블록이 이 방식이고, 블록 하나가 파일 하나다.

다음 강의부터 이 문법으로 문서를 잘라 검색하는 것을 직접 만든다.

Share
  • 파이썬
  • AI
  • 문법
  • 기초
  • 반복문