최근 수정 시각 : 2024-10-03 13:56:43

Python/문법

파일:상위 문서 아이콘.svg   상위 문서: Python
프로그래밍 언어 문법
{{{#!wiki style="margin: -16px -11px; word-break: keep-all"<colbgcolor=#0095c7><colcolor=#fff,#000> 언어 문법 C(포인터 · 구조체 · size_t) · C++(자료형 · 클래스 · 이름공간 · 상수 표현식 · 특성) · C# · Java · Python(함수 · 모듈) · Kotlin · MATLAB · SQL · PHP · JavaScript · Haskell(모나드)
마크업 문법 HTML · CSS
개념과 용어 함수(인라인 함수 · 고차 함수 · 람다식) · 리터럴 · 상속 · 예외 · 조건문 · 참조에 의한 호출 · eval
기타 #! · == · === · deprecated · NaN · null · undefined · 배커스-나우르 표기법
프로그래밍 언어 예제 · 목록 · 분류 }}}

1. 개요
1.1. 코딩 스타일
2. 자료형
2.1. 숫자(Number)2.2. 리스트(List), 튜플(Tuple)2.3. 문자열(String)2.4. 딕셔너리(Dictionary)2.5. 불(bool)
2.5.1. Truthy/Falsy
2.6. Data Type(자료형 변환)
3. 입출력4. 들여쓰기5. 조건문
5.1. 2항 연산자5.2. 3항 연산자
6. 반복문
6.1. for 문6.2. while 문
7. 함수8. 모듈9. 슬라이싱10. map11. 예외 처리12. 클래스13. 팁

1. 개요

이 문서는 Python의 문법을 설명한다. 기준은 3.x.x대이다.

1.1. 코딩 스타일

여러 사람들이 같이 프로젝트를 할 때는, 통일된 방식으로 문서를 짜는 게 가독성과 유지 보수 면에서 편리하다.

가장 유명한 방식은 Python의 창시자 '귀도 반 로섬'이 제시한 코딩 스타일인 PEP-8 이다. PEP-8 코딩 스타일 한국어 번역판

2. 자료형

C, Java와 달리 파이썬은 변수를 선언할 때 따로 자료형을 지정하지 않는다. 내부적으론 자료형이 있으나 런타임에서 인터프리터가 추론한다.(단, 파이썬 3.6부터 기본 패키지인 typing을 사용하여 정적 타이핑이 가능하다.)

파이썬은 객체 지향 언어이고 원시 자료형이 없기 때문에 모든 값은 반드시 객체로 간주된다. 따라서 모든 데이터의 자료형은 그 데이터의 클래스이다. type() 함수로 변수의 자료형을 확인할 수 있다.

type은 사실 파이썬 모든 자료형의 원형이기도 하다. 메타클래스를 배우게 되면 알 수 있다.
#!syntax python
class Value:
    pass

var = Value()
print(type(var)) # <class '__main__.Value'>

2.1. 숫자(Number)

정수(int)는 길이 제한이 없어 큰 수도 별도의 자료형을 지정하지 않고 작은 수와 똑같이 다룰 수 있는 편리함을 지닌다. 실수는 8바이트로 제한된다.
#!syntax python
a = 1234 # 정수형
b = 3.14 # 실수형
print(type(a), type(b)) # <class 'int'> <class 'float'>

2.2. 리스트(List), 튜플(Tuple)

파이썬의 리스트는 말 그대로 순서대로 저장하는 시퀀스이자 변경 가능한 목록(Mutable List)을 말한다. 입력 순서가 유지되며, 내부적으로는 동적 배열로 구현되어 있다.
파일:3-7-2.png
타 언어의 배열처럼 파이썬도 array라는 배열에 해당하는 모듈을 제공하긴 하지만 기본적인 기능만을 제공하며, 사실상 리스트가 배열의 역할을 대체한다. 파이썬의 리스트는 다른 언어에서 제공하지 않는 매우 다양하고 편리한 기능을 제공한다. 리스트를 사용하면 사실상 스택(자료구조)을 사용할지 큐(자료구조)를 사용할지를 고민하지 않아도 되며, 스택과 큐에서 사용 가능한 모든 연산을 동시에 제공한다. 리스트는 객체로 되어 있는 모든 자료형을 다음 그림과 같이 포인터로 연결하는 구조로 되어 있다.
파일:2-5-2.png
파이썬은 모든 것이 객체며, 파이썬의 리스트는 이들 객체에 대한 포인터 목록을 관리하는 형태로 구현되어 있다. 사실상 연결 리스트에 대한 포인터 목록을 배열 형태로 관리하고 있으며, 그 덕분에 파이썬의 리스트는 배열과 연결리스트를 모두 합친 듯이 강력한 기능과 문법을 제공한다.

리스트는 객체가 수정 가능하지만, 튜플은 최초 생성 이후 수정이 불가능하다. list()tuple() 함수를 통해 서로 형 변환이 가능하다. 고차원 리스트도 가능하다.
#!syntax python
l = [1, 2, 3] #일차원 리스트
t = tuple(l) #튜플로 변환
li = list(t) #리스트로 변환
l = [[1, 2, 3], [1, 2, 3]] #이차원 리스트

리스트와 튜플의 값을 참조할 때에는 변수명[숫자]의 형태로 입력한다. 아래는 각각 일차원 리스트, 이차원 리스트, 튜플의 값을 출력하는 코드이다.
#!syntax python
li_one = [1, 2, 3] # 일차원 리스트
li_two = [[1, 2, 3], [4, 5, 6]] # 이차원 리스트
tu = (7, 8) # 튜플

print(li_one[0], li_two[0][1], tu[1]) # 1 2 8
이때 아래와 같이 작성하면 리스트, 튜플에 없는 원소를 참조하기 때문에 오류가 발생한다.
#!syntax python print(li_one[3], li_two[2][1], tu[2])
Traceback (most recent call last):
  File "[파일명]", line 1, in <module>
IndexError: list index out of range

2.3. 문자열(String)

글자로 이루어진 변수를 스트링 변수라고 한다. 따옴표를 이용하여 표기한다.
#!syntax python
>>> a = 'text'

따옴표를 이용하지 않으면 오류가 걸린다.
#!syntax python
>>> a = text
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'text' is not defined
text라는 변수가 정의되었으면 오류가 안 걸린다.

사용할 수 있는 따옴표로는 작은 따옴표('), 큰 따옴표("), 작은 따옴표 3개('''), 큰 따옴표 3개(""")가 있다. 스트링 안에 따옴표 문자가 들어갈 때 사용한다. 또 줄바꿈을 포함시킬 수 있다.
#!syntax python
a = " ' 를 포함한 문장"
b = ''' " 을 포함한 문장'''

2.4. 딕셔너리(Dictionary)

파이썬의 딕셔너리는 키/값 구조로 이뤄진 딕셔너리를 말한다. 파이썬 3.7 이상에서는 입력 순서 또한 유지되며, 내부적으로는 해시 테이블(Hash Table)로 구현되어 있다. 3.6 이하에서는 입력 순서를 보장하지 않으므로 유의해야 한다. 중괄호를 사용해서 선언한다.
#!syntax python
a = {}

다음과 같이 key1, key2는 초깃값으로 지정해 선언하거나 key3처럼 나중에 별도로 선언하여 value3라는 값을 할당할 수 있다.
#!syntax python
>>> a = {'key1':'value1', 'key2':'value2'} 
>>> a
{'key1': 'value1', 'key2': 'value2'}
>>> a['key3'] = 'value3'
>>> a
{'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}

키에는 해시가능한(hashable) 자료형만 가능하며, 값에는 리스트 뿐만 아니라 집합 자료형 등 모든 자료형이 가능하다.
#!syntax python
>>> a = {'key1':[1, 2, 3], 'key2': (4, 5, 6)}
>>> a
{'key1': [1, 2, 3], 'key2': (4, 5, 6)}

2.5. 불(bool)

bool이란 참(True)과 거짓(False)으로만 이루어진 자료형이다. 대문자를 쓴다는 점이 다른 프로그래밍 언어와 독특하게 구분된다. 소문자로 쓰면 예약어로서 기능하지 않는다.
#!syntax python
>>> a == 1
이라고 입력하면 a가 1이라면 'True', 그 외의 것이라면 'False'가 출력된다.

참, 거짓도 변수로 만들 수 있다. 아래와 같이 직접 True 또는 False 값을 할당시켜 쓸 수 있다.
#!syntax python c = True
if x > 10:
    c = False

아래와 같이 하면 hello를 계속 출력하는 것처럼 무한 루프를 만들 수도 있다.
#!syntax python
while True:
    print('hello')

주의할 점은 무조건 True/False로만 입력해야 한다는 것이다.
#!syntax python
>>> isntTrue = true # 에러 발생.
대소문자가 달라져 버리면[1] 아래와 같이 예외가 발생한다.
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
NameError: name 'true' is not defined.

2.5.1. Truthy/Falsy

일부 언어와 마찬가지로, 파이썬도 특정 값이나 객체에 참 또는 거짓의 논리를 부여할 수 있다. 이는 논리 연산을 할 때 매우 유용하게 사용할 수 있다.

예를 들어 문자열이 유효한지 검사할 때
#!syntax python
string = ''
if len(string) > 0: ~
이렇게 해야 할 것을
#!syntax python
string = ''
if string: ~
와 같이 손쉽게 처리할 수 있다.

파이썬에서 기본적으로 특정 논리를 갖는 값은 다음과 같다.
  • Truthy: True, 0이 아닌 수, 유효한 문자열(비지 않은 문자열), 유효한 리스트, 유효한 튜플
  • Falsy: False, None, 0, 빈 문자열, 빈 리스트, 빈 튜플 등

그 외에도 자체적으로 선언한 객체에 bool 논리를 부여해 주려면 __bool__ 메소드를 사용하면 된다. __bool__ 메소드가 없는데 __len__ 메소드가 있다면 해당 메소드에 따라 길이가 0이면 False, 0보다 크면 True로 간주하고, __bool__, __len__ 둘 다 없으면 무조건 True로 취급한다. (객체 선언은 클래스 문법을 참고하자.)
#!syntax python
class Value:
    def __init__(self):
        self.valid = False
    def __bool__(self):
        return self.valid
    def setValidity(self, validity):
        self.valid = validity

var = Value()
print(bool(var))  # False
var.setValidity(True)
print(bool(var))  # True

class Stack:
    def __init__(self):
        self.stack = list()
    def __len__(self):
        return len(self.stack)
    def push(self, x):
        self.stack.append(x)
    def pop(self):
        return self.stack.pop()

stack = Stack()
print(len(stack))   # 0
print(bool(stack))  # False

stack.push(100)     # 100 입력
print(len(stack))   # 1
print(bool(stack))  # True

stack.pop()         # 100 출력
print(len(stack))   # 0
print(bool(stack))  # False

2.6. Data Type(자료형 변환)

자료형(바꿀 변수)의 형태로 아주 간단하게 변경 가능하다.
  • str() - float형이나 int형을 문자열로 변환할 때 사용한다. 제일 기본적으로 쓰인다.
  • int() - 정수형으로 바꾼다. 양의 실수와 음의 실수 모두 소수점을 버린다.
  • float() - 실수형으로 바꾼다.
  • complex() - 복소수형으로 바꾼다. 허수는 i가 아니라 j로 표기한다.
  • list() - 리스트로 바꾼다. tuple과 형변환에 자주 사용된다.
  • tuple() - 튜플로 바꾼다. list와의 형변환에 자주 사용된다.
  • set() - 세트형(집합형)으로 바꾼다. 리스트나 튜플은 중복 원소를 허용하지만 세트는 중복을 허용하지 않으므로, 임의의 리스트나 튜플을 세트형으로 변환시키면 중복이 자동으로 제거되는 유용함을 지닌다.

앞서 언급했듯 파이썬의 모든 자료형은 '클래스'이므로 사용자 정의 클래스 자료형으로 바꿀 때도 똑같은 방법으로 하면 된다.

3. 입출력

기본적으로 출력은 print() 함수를 사용한다. 따로 줄바꿈을 추가하지 않아도 자동으로 줄바꿈까지 출력한다.
#!syntax python
# Hello, world! 문자열 출력 
print("Hello, world!")

변수를 출력하는 방법은 여러가지가 있다.
#!syntax python
a = 10
b = 20

# 10 , 20 출력
# 1. 인자 여러개로 주기
print(a, "," , b)

# 2. c 스타일 
print("%d , %d" % (a,b))

c 스타일에다가 %f를 쓰면 float형을 출력 할 수 있고, %f.2를 넣으면 소수점 아래 2자리까지 출력된다. 2는 다른 숫자로 대체 가능하다.
#!syntax python
# 3. format 함수
print("{} , {}".format(a, b))

# 4. f-string
print(f"{a} , {b}")

print()에 인자를 여러개 준 경우 각각의 문자열이 한 칸 공백을 두고 출력된다.

끝의 문자에 줄바꿈이 아닌 다른 문자열이 포함되게 할 수 있다.
#!syntax python
print("a", end="") #공백 없음
print("b")

이런 식으로 입력하면 ab 식으로 연달아서 출력된다.

그리고 print에 여러 문자열을 넣고, 그 사이에 다른 문자열이 포함되도록 할 수 있다.
#!syntax python
print("하", "하", "하", sep = ".")
이러면 하.하.하 식으로 출력된다.

입력은 input()을 사용한다.

input()은 기본적으로 str 형태로 값을 받으며, 특정 자료형 함수를 이용하면 다른 형으로 값을 받을 수 있다. 그 자료형으로 값이 입력되지 않는다면[2] 예외 오류가 일어난다.
#!syntax python
a = input("---->")
b = int(input("---->"))
c = float(input("---->"))
이렇게 쓰면 출력창에 ---->라는 메시지가 나타나며, 커서가 그곳으로 이동되어 입력을 할 수 있다. 그러면 각각 a, b, c 변수에 그 값이 저장된다.

입력에서 걸리는 시간을 줄이려면 sys 모듈의 stdin.readline()을 이용하면 좋다. 다만, 이 경우는 input()과는 달리 입력받는 기능만을 할 수 있다.
#!syntax python
import sys
a = sys.stdin.readline()
b = int(sys.stdin.readline())
c = float(sys.stdin.readline())

4. 들여쓰기

Python 특유의 디자인 철학에 따라 Python은 분기문과 반복문 등을 사용할 때 들여쓰기를 행해야 한다. 보통 권장되는 것은 네 칸 띄어쓰기이지만, Python 자체에서 자동 들여쓰기의 칸수를 결정할 수 있고 Tab은 권장되지 않으나 일부 텍스트 에디터에서 Tab의 스페이스 개수를 설정할 수 있기 때문에 큰 문제는 아니다. 아래처럼 하나의 구문 안에서 서로 다른 들여쓰기 깊이를 섞어서 쓰면 IndentationError 에러가 발생한다.
#!syntax python
if True:
  print("Hello world")    # 두 칸 들여쓰기
    print("Hello world")  # 네 칸 들여쓰기

5. 조건문

python의 조건문에서는 if, else 그리고 else if를 축약한 elif가 쓰인다. 예를 들어 부호 함수는 다음과 같이 쓸 수 있다.
#!syntax python
n = int(input("숫자를 입력하세요 ---->"))
if n > 0:
    print(f"{n}은 양수 입니다.")
elif n < 0:
    print(f"{n}은 음수입니다.")
else:
    print(f"{n}은 0입니다.")

사실 이 경우는 다음과 같이 써도 제대로 동작한다.
#!syntax python
n = int(input("숫자를 입력하세요 ---->"))
if n > 0:
    print(f"{n}은 양수 입니다.")
if n < 0:
    print(f"{n}은 음수입니다.")
if n == 0:
    print(f"{n}은 0입니다.")

다만 위와의 차이점은, elif는 위의 조건이 맞지 않고 해당 조건과 일치 할 시 출력하는 것이고, if는 조건만 맞으면 출력하는 거다. 이러한 상황에는 모두 if로 써도 상관이 없지만, 상황에 따라 오류가 날 수 있다.

다음은 변수 x의 대소 관계를 비교하는 코드이다.
#!syntax python
a = 120
if a > 100:
    print(1)
elif a > 50:
    print(2)
else:
    print(3)

이러한 상황에서 elif를 if로 바꾼다면, 1과 2가 모두 출력될 것이다. 왜냐면 120은 100보다도 크고 50보다도 크기 때문이다. 이러한 상황에 elif를 쓰는 것이다.

5.1. 2항 연산자

2항 연산자는 참의 논리(Truthy)를 갖는 값을 갖는다. ||&&가 아니라 orand가 쓰인다.
#!syntax python
x or y
#!syntax python
var = 'Hello' or []
print(var) # 결과는 'Hello'
#!syntax python
if True and False:
    print("true!")
else:
    print("false!")

# 결과는 'false!'

5.2. 3항 연산자

3항 연산자는 참인 경우와 거짓인 경우 다른 값을 갖는 것으로 아래 코드는 TTrue일때 x, False일 때 y의 값을 갖는다.
#!syntax python
x if T else y
아래 코드는 부호 함수를 구현한다.
#!syntax python
def sgn(x):
    return 1 if x > 0 else (0 if x == 0 else -1)

6. 반복문

Python에서는 다음과 같이 반복문을 작성한다.

6.1. for 문

#!syntax python
for x in X:
    todo

# 혹은

for i in range(start, stop[, step]):
    todo
위 코드는 배열 또는 range 형태인 X의 각 원소 x에 대해서 todo를 실행한다.

아래 코드는 0부터 9까지의 정수를 한 줄에 하나씩 출력한다. range는 0부터 n-1까지의 값을 담는 코드[3]인데, irange의 값을 하나씩 넣으며 반복한다는 코드이다. 이러면 총 10번 반복되게 된다.
#!syntax python
for i in range(10):
    print(i)

기본적으로 한 개의 매개변수를 전달할 때는 start의 기본값은 0, step의 기본값은 1로 설정되며, 0부터 (전달값 - 1)까지의 수를 하나씩 가져와 i에 저장한다.

아래와 같이 하면 xi를 더하며 1부터 10까지 더한다.
#!syntax python
x = 0
for i in range(1, 11):
    x += i
    print(x)

아래 코드는 이중 for 문을 사용 해 구구단을 출력하는 코드이다.
#!syntax python
for i in range(2, 10):
    print(f"------ {i}단 -----")
    for j in range(1, 9):
        print(f"{i} x {j} = {i * j})

아래 코드는 n과 m을 입력받아 m이 n보다 클 경우, n부터 m까지의 숫자를 출력하는 코드이다.
#!syntax python
n = int(input("시작할 숫자를 입력하세요 ----> "))
m = int(input("끝낼 숫자를 입력하세요 ----> "))
for i in range(n, m + 1):
    print(i)

아래 코드는 n과 m을 입력받아 n이 m보다 클 경우, m부터 n까지의 숫자를 출력하는 코드이다.
#!syntax python
n = int(input("시작할 숫자를 입력하세요 ----> "))
m = int(input("끝낼 숫자를 입력하세요 ----> "))
for i in range(n, m - 1,-1):
    print(i)

6.2. while 문

아래 코드는 C라는 조건이 만족되는 동안 todo를 계속 실행하며, 해당 조건이 더 이상 만족되지 않으면 while문을 탈출한다. C라는 조건이 항상 참이면 무한 루프에 걸릴 수 있으니 주의하라. 이를 이용해서 계속해서 반복해서 작동해야하는 프로그램의 경우에 while True:문을 이용하기도 하며, 1을 논리형으로 변환하면 True가 되므로 while 1: 로 사용하는 경우도 있다.
#!syntax python
while C:
    todo

아래 코드는 i가 10보다 작은 동안 i를 출력한 다음 1씩 증가시키므로, 0부터 9까지의 정수를 한 줄에 하나씩 출력한다.
#!syntax python
i = 0
while i < 10:
    print(i)
    i += 1

아래와 같이 하면 사용자가 m을 맞출 때 까지 반복되고, 10번 시도하면 힌트를 알려준다.
#!syntax python
n = 0
m = 124
count = 0
while n != m:
    n = int(input("숫자를 맞혀보세요 ---->"))
    count += 1
    if n > m:
        print("조금만 더 작게 해보세요.")
    if n < m:
        print("조금만 더 크게 해보세요.")
    if n == m:
        print("축하합니다! 정답입니다!")
    if count == 10:
        print("Hint : 100~130 이내")

7. 함수

파일:상세 내용 아이콘.svg   자세한 내용은 Python/문법/함수 문서
번 문단을
부분을
참고하십시오.

8. 모듈

파일:상세 내용 아이콘.svg   자세한 내용은 Python/문법/모듈 문서
번 문단을
부분을
참고하십시오.

9. 슬라이싱

파이썬에서는 슬라이싱이라는 매우 편리한 기능을 제공한다. 무엇보다 내부적으로 매우 빠르게 동작한다. 위치를 지정하면 해당 위치의 배열 포인터를 얻게 되며 이를 통해 연결된 객체를 찾아 실제 값을 찾아내는데, 이 과정은 매우 빠르게 진행되므로 리스트나 문자열을 조작할 때는 항상 슬라이싱을 우선으로 사용하는 편이 속도 개선에 유리하다.
파일:2-6-1.png
<rowcolor=#373a3c> 문법 결과 설명
S[1:4] 녕하세 인덱스 1에서(0부터 시작) 4 이전까지(4는 포함하지 않는다) 표현한다. 4개를 의미하는 게 아니므로 유의해야 한다.
S[1:-2] 녕하 인덱스 1에서 -2 이전까지(-2는 포함하지 않는다) 표현한다. 뒤에서부터는 음수로 접근이 가능하다.
S[1:] 녕하세요 문자열의 시작 또는 끝은 생략 가능하다.
S[:] 안녕하세요 둘 다 생략하면 사본을 리턴한다. 파이썬은 a=b와 같은 형태로 할당하면 변수의 값이 할당되는 것이 아니라 a 변수가 b 변수를 참조하는 형태가 된다.
참조가 아닌 값을 복사하기 위해[:]를 사용할 수 있으며, 이 방식은 문자열이나 리스트를 복사하는 파이썬다운 방식(Pythonic Way)이기도 하다.
S[1:100] 녕하세요 인덱스가 지나치게 클 경우 문자열의 최대 길이만큼만 표현된다. S[1:] 과 동일하다.
S[-1] 마지막 문자(뒤에서 첫 번째)
S[-4] 뒤에서 4번째
S[:-3] 안녕 뒤에서 3개 글자 앞까지
S[-3:] 하세요 뒤에서 3번째 문자에서 마지막까지
S[::1] 안녕하세요 1은 기본값으로 동일하다.
S[::-1] 요세하녕안 뒤집는다.
S[::2] 안하요 2칸씩 앞으로 이동한다.

10. map

#!syntax python
map(func, *iterables)
리스트, 튜플, 문자열 등 Iterable한 객체의 요소마다 어떤 처리를 할 때 유용하게 사용할 수 있는 클래스이다.(함수가 아니다. int도 클래스이지만 int(*)로 실수를 버림하거나, 문자열을 정수로 바꾸는 것과 마찬가지이다. 물론 파이썬은 순수 객체지향 언어이기에 map이 클래스냐 함수냐 따지는 것은 크게 의미가 없다. 어차피 함수도 객체의 일종으로 취급받는다.)

기본적인 골자는 두 번째부터 받은 Iterable의 요소마다 첫 번째 인자로 받은 함수로 처리해 새로운 Iterable을 생성하는 것이다. *iterable에서 짐작할 수 있듯이, 여러 개의 Iterable를 받는 것이 가능하다. 다음은 예시이다.
#!syntax python
print(''.join(map(lambda x, y: x + y, "Hello", "World"))) # "HWeolrllod"가 출력됨.
map 클래스 또한 Iterable한 객체이기 때문에 결과물을 담고자 하는 자료형으로 변환해줄 필요가 있다.
#!syntax python
map_obj = map(lambda x, y: x + y, "Hello", "World")

result_list = list(map_obj)
# 또는
result_list = [*map_obj] # *을 이용한 unpack

result_tuple = tuple(map_obj)
# 또는
result_tuple = (*map_obj,) # *을 이용한 unpack
추가적으로 이를 활용하여 매우 편리하게 입력을 처리할 수 있다.

다음은 숫자 여러 개를 입력받아 형변환 후 input_list라는 리스트에 넣어주는 코드이다.
#!syntax python
input_list = list(map(int, input().split()))

11. 예외 처리

여느 프로그래밍 언어와 비슷하게 예외 처리를 지원한다. 예외를 던질 때에는 raise 키워드를 사용한다.
#!syntax python
try:
    # 정상 작업
except BaseException as e:
    # 예외를 처리하기 위해 수행할 작업
else:
    # 예외가 발생하지 않았을 때 수행할 작업
finally:
    # 예외 여부에 관계없이 반드시 수행할 작업

다음과 같이 Exception 객체를 상속받아 사용자 정의 예외 객체를 만들 수 있다.(12번 문단에서 자세히 설명한다.)
#!syntax python
class CustomException(Exception):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return self.value

try:
    raise CustomException("Error!!")
except CustomException as e:
    print(e) # "Error!!"이 출력된다.

12. 클래스

  • 클래스는 여러 똑같은 것을 선언할 때 쓰인다.
  • 클래스가 필요한 이유는, 덧셈 계산기 2개를 만들고, 각각의 계산기로 1+2, 2+3을 출력하려고 한다고 하자, class를 사용하지 않으면 아래처럼 쓸 수 있는데 여기에 기능을 추가하거나 수를 늘리려면 일일히 함수, 변수를 선언해야 하는 불편함이 있다.
    {{{#!syntax python
def cal1(a, b):
return a+b

def cal2(a, b):
return a+b

print(cal1(1, 2))
print(cal1(2, 3))
}}}
  • 하지만 클래스를 사용하면 아래처럼 쓸 수 있다.
    {{{#!syntax python
class Calculater:
def cal(self, a, b):
return a+b

c1 = Calculater()
c2 = Calculater()
print(c1.cal(1, 2))
print(c2.cal(2, 3))
}}}
  • 수를 늘릴 땐 변수를 늘리면 되고, 기능 추가는 Calculater만 바꾸면 되므로 훨씬 수월해진다.(자세한 것은 아래 내용 참고하라.)
  • 파이썬의 클래스는 선언할 때 class 키워드를 쓴다.
    {{{#!syntax python
class 클래스:
pass}}}* 빈 클래스를 만들 때는 pass 문법을 쓴다.* 객체를 만들 때는 이렇게 쓴다.{{{#!syntax python
변수 = 클래스명()
}}}
  • 생성자는 __init__을 사용한다. 그리고 함수를 정의할 땐 반드시 self(자신)을 매개변수로 받아야 한다.(이름은 상관없지만 주로 self를 쓴다.)
  • 상속받을 때는 이렇게 쓴다.
    {{{#!syntax python
class 자식클래스(부모클래스):
추가할내용
}}}
  • 상속받으면 부모 클래스의 기능을 자식 클래스에서도 쓸 수 있다.
  • 객체변수는 각 객체가 가진 변수로, 클래스 내의 함수에서 생성/변경하려면 self.변수명을 사용하면 된다.
  • 클래스변수는 모든 객체가 공유하는 변수로, 함수 밖에서 선언한다.

13.

  • 문자열을 합칠 때 join을 쓰자. range 함수와 str 함수를 같이 쓰면 매우 편해지는 경우가 있다.
    {{{#!syntax python
''.join(str(x) for x in range(10))
}}}
  • 슬라이스(slice) 문법은 리스트/문자열의 부분을 잘라내는 것 이외에도 다양한 활용이 가능하다.
    {{{#!syntax python
# 문자열 뒤집기
a = 'abc'
print(a[::-1]) # 출력: cba

# 리스트 복사
a = [1, 2, 3]
b = a[:]
print(b) # 출력: [1, 2, 3]
print(a is b) # 출력: False

c = 1, 2], [3, 4
d = c[:]
c[0] = [5, 6] # 리스트 자체는 복사되지만
c[1][0] = 7 # 리스트의 원소들까지 복사되지는 않으므로 주의해서 사용하자.
print(c) # 출력: 5, 6], [7, 4
print(d) # 출력: 1, 2], [7, 4
print('%s, %s, %s' % (c is d, c[0] is d[0], c[1] is d[1])) # 출력: False, False, True
}}}
  • 숫자, 문자, 튜플은 변경 불가능(immutable)하며, 리스트, 집합, 딕셔너리는 변경 가능(mutable)하다. 이때 변경 가능한 자료형은 다른 변수에 대입하여도 그 내용이 공유된다. 그 예로, 아래와 같은 코드가 있다고 하자.
    {{{#!syntax python
a = (1, 2, 3)
b = a
b += (2, 1)
print(a) # 출력: (1, 2, 3)
print(b) # 출력: (1, 2, 3, 2, 1)
}}}
  • 우리가 예상한대로, 튜플 b만 변경되고, a는 변경되지 않는다. 위의 코드에서 튜플(immutable)을 리스트(mutable)로 바꾸어 보자.
    {{{#!syntax python
a = [1, 2, 3]
b = a
b += [2, 1]
print(a) # 출력: [1, 2, 3, 2, 1]
print(b) # 출력: [1, 2, 3, 2, 1]
}}}
  • 출력을 보면 b만 변경했음에도 a가 변한다는 사실을 알 수 있다. 이것은 모든 변경 가능한 자료형에 적용되며, 심지어 리스트 안의 리스트 같은 것들까지도 공유가 된다. 그러니 원본을 변경하면 안 되는 경우에는 list(), set(), dict()copy 모듈 등을 이용해서 객체를 복제하고 작업하자. 변경 불가능한 자료형은 원본을 변경할 수 없기 때문에 해당 사항이 없다.
  • 특히 listdict 자체를 함수에 인자로 전달받을 때 내부에서 리스트를 변형하는 연산을 하면 함수 밖에서도 listdict가 변형되니 주의하도록 하자.
  • list.insert(0)list.append()는 각각 첫 번째 자리에 값을 추가하거나, 마지막 자리에 값을 추가하는 정도의 조그만한 차이일 뿐이지만, 계산 시간이 [math(O(n))]과 [math(O(1))] 수준으로 차이가 나기 때문에 첫 번째 방법은 쓰지 않는 것이 좋다.
  • 그래서 prepending에 의존하는 하는 알고리즘을 파이썬 리스트로 구현하려면, 알고리즘을 거꾸로 뒤집는 것이 좋고, 만약 알고리즘을 뒤집기 힘들다면, 파이썬 공식 라이브러리에서 제공하는 deque 같은 것을 써야 한다. 자료구조 개념에 대한 감각이 있으면 이해하기 쉽다.
  • CPython같은 경우 JIT를 쓰지 않기 때문에 이런 것을 자동으로 최적화해 준다고 생각하지 말자.
  • 괄호 안에 for와 if, else를 넣을 시 주의하자.
    {{{#!syntax python
# 1
list(x for x in range(10) if x%2 == 0)
# 2
list(x for x in range(10) if x%2 == 0 else 0)
# 3
list(x if x%2 == 0 else 0 for x in range(10))
}}}
  • 1은 되지만 2는 되지 않으며 3은 된다. if만 넣을 경우 for 뒤에 써야 하며, 조건을 충족하지 않는 원소들은 생략된다.(즉, 1의 결과물은 [0, 2, 4, 6, 8]이다.) if와 else 모두를 넣는다면 for 앞에 넣어야 하며 조건을 충족하면 맨 앞, 아니라면 else 다음이 반환된다.
  • 아래처럼 반복문을 돌 때 변수가 필요 없는 경우에는 변수 이름을 _로 한다.
    {{{#!syntax python
for _ in range(3):
print("spam")
}}}
  • 멀티프로세싱은 __main__ 블럭 안에 들어가야 한다. 네임스페이스 문제 때문이다. 들어가지 않으면 오류를 뿜는다.
    {{{#!syntax python
#if 대신 while도 가능.
if name == 'main':
}}}
  • 반복문을 사용할 때 유도 변수 (i, j 등)을 사용하지 않고 for value in mylist와 같이 사용할 수 있는 것은 python의 큰 장점이다. 그럼에도 불구하고 인덱스를 사용해야 하는 경우 for i in range(len(mylist))처럼 쓰거나 count 변수를 임시로 생성하지 말고 enumerate를 사용하자.
    {{{#!syntax python
mylist = [10, 20, 30, 40]
# 이렇게 하지 말고,
for i, value in enumerate(mylist):
print(mylist[i])
...
}}}
  • 파이썬 2와 3에서의 range는 리턴 형식이 다르다. 2에서는 리스트를 리턴하지만 3에서는 range 객체를 리턴한다. 따라서 3에서 range를 리스트로 바꾸려면 아래와 같은 방법들로 전환해야 한다. 파이썬 2에 익숙한 사람은, 파이썬 3의 range는 파이썬 2의 xrange와 동일한 역할을 한다고 생각하면 된다.
    {{{#!syntax python
list(range(10))
[range(10)]
}}}
  • 그 외에도 파이썬 2와 3은 정수 나눗셈, print 문법, 문자열 종류, import 방식 같은 데서 차이가 많이 나는 편이다. 일부는 __future__라는 라이브러리에서 파이썬 2에서도 3과 같은 문법을 쓸 수 있도록 해 주는 기능을 제공하고 있지만, 그렇지 않은 부분들은 stack overflow 등을 참고해서 직접 만들어서 쓰는 것이 좋다. 현재 많은 오픈 소스 라이브러리들이 __future__로 도배되어 있고 가내 수공업 식으로 호환성을 땜질해 있는 것을 보면 말이다. 파이썬 2.7이 공식적으로 지원이 중단되면 시점까지 많은 라이브러리들이 파이썬 2 지원을 철회할 계획을 가지고 있으므로, 그때가 되면 이런 호환성 문제에서 숨통이 트일 것이다.
  • 파이썬 암호화 라이브러리 pycrypto 설치를 시도하면 아래와 같은 에러가 발생한다. 이럴 때는 관련 도구를 추가로 설치해야 한다.[5]
    {{{error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools
}}}
  • Bolierplate 코드가 적고, 리스트와 셋, 해시 등의 자료구조를 간단한 기호로 표기할 수 있어 코딩 테스트 시 많이 사용되는 언어이기도 하다. Python으로 코드를 작성하면 같은 알고리즘을 C++, Java 등으로 구현했을 때보다 전체적인 코드 길이가 비약적으로 짧아진다.
  • 파이썬 인터프리터라도 열어서 아무 모듈이나 임포트하거나, print 함수에 대해 dir(print)를 입력해보면 파이썬의 구조를 좀 더 잘 알게 된다. 우리가 사용했던 함수가 다르게 보일 것이다.
  • 과학 계산 시 numpy를 자주 이용하는데, for문을 이용하기보다는 배열을 이용해 처리하는 vectorize 테크닉을 사용하자. 이것조차 안 된다면 numba라는 JIT 컴파일 라이브러리를 이용해서 성능을 향상시킬 수 있다.


[1] 주로 다른 언어를 하다 Python으로 넘어오는 프로그래머들이 저지르는 실수이다.그러나 파이썬하다 다른 언어하면 대문자로 써서 오류난다.[2] 예시: int(input())이라 써놓고 문자열이 입력될 시[3] 그렇다고 print(range(10))식으로 적으면 출력되지 않는다.[range(10)] [5] http://freesugar.tistory.com/37