본 문서는 파이썬 코딩의 기술: Effective Python의 정리 내용입니다. 인용구문은 필자의 견해 또는 개인적인 궁금함을 담은 내용입니다.
python python --version
import sys
print(sys.version_info)
print(sys.version)
https://www.python.org/dev/peps/pep-0008/ 참고
if
문안에서 False
를 리턴한다.Python3
에서는 bytes
, str
두가지 타입으로 문자 시퀀스를 표현bytes
는 raw 8 비트 값을 저장str
은 유니코드 문자를 저장Python2
에서는 unicode
, str
두가지 타입으로 문자 시퀀스를 표현str
는 raw 8 비트 값을 저장unicode
는 유니코드 문자를 저장ASCII(American Standard Code for Information Interchange)는 미국에서 정의한 표준화 부호체계로 010101 같은 이진 숫자를 통해 문자를 표현하기 위해 고안되었다.
아스키코드는 문자를 표현하기 위해 1바이트를 7비트와 통신 에러 검출을 위한(Parity Bit) 1로 사용한다. 총 2^7=128개의 문자를 표현 할 수 있는데 이는 영문 키보드로 입력 할 수 있는 케이스들만 커버가 가능하기에 1비트 확장한 ANSI 코드가 나왔다.
그러나 한글, 중국어 등 여러 국가에 언어에서는 제약이 있었다. 그리하여 Unicode라는 전 세계 언어 문자 정의를 위한 국제 표준 코드가 등장하였다.
참고: 아스키(ASCII)코드와 유니코드(Unicode)의 이해
rb
혹은 wb
로 오픈한다.somelist[start:end:step]
a[:5]
, a[2:]
a[0] vs a[:1]
전자는 빈 리스트일 경우index error
발생, 반면 후자는 [] 빈 리스트를 반환한다.
슬라이싱은 인덱스 범위가 벗어나도 자동으로 범위를 맞춰준다.
참고 - Why does Python allow out-of-range slice indexes for sequences?
s = list("five little monkeys")
i = s.index('l')
n = len('little')
s[i : i+n ] = list("humongous")
''.join(s)
>> 'five humongous monkeys'
a = [1, 2, 3, 4]
# comprehension
even_squeres = [x**2 for x in a if x % 2 == 0]
# map, filter
even_numbers = filter(lambda x: x % 2 ==0, a)
even_sequeres = map(lambda x: x**2, even_numbers)
javascript
와 같이map
,filter
를 체이닝해서 사용하고자 한다면map
과filter
를 오버라이드 하거나, PyFunctional와 같은 라이브러리를 사용할 수 있다.
참고글 : What is the Python way of chaining maps and filters?
matrix = [[1,2,3], [4,5,6], [7,8,9]]
flag = [x for row in matrix for x in row]
>>> [1, 2, 3, 4, 5, 6, 7, 8, 9]
## condition by loop level
filtered = [[x for x in row if x % 3 == 0]
for row in matrix if sum(row) >= 10 ]
>>> [[6], [9]]
comprehension
의 문제점은 새로운 메모리에 시퀀스(리스트, 딕셔너리 등) 객체를 새로 생성한다는 점이다. 따라서 메모리를 비교적 많이 사용한다.generator expression
은 시퀀스를 모두 메모리에 로딩하지 않고 한 번에 한 아이템을 내주는 iterator
를 리턴한다generator expression
은 () 문자 사이에 컴프리헨션과 비슷한 문법으로 생성한다.iter = (len(x) for x in [1,2,3]) # generator expression
next(it)
>>> 1
next(it)
>>> 2
제너레이터는
__iter__
를 통해 생성 할 수 있다. 함수 본체 안에yield
키워드를 가진 함수는 모두 제너레이터 함수이다. 함수는 값을 반환하고, 제네레이터 함수는 제네레이터 객체가 반환된다.
next()
는 함수 본체에 있는 다음yield
로 진행하며, 함수 본체가 반환 될 때(return) 이를 포함하고 있는 제너레이터 객체가 평가 될 때는 Itertor 프로토콜에 따라StopIteration
예외를 발생시킨다.
iter = (len(x) for x in [1,2,3])
squere_tuple_iter = ((x, x**2) for x in iter)
next(squere_tuple_iter)
>>> (1, 1)
next(squere_tuple_iter)
>>> (2, 4)
enumerate
는 이터레이터를 순회하면서 각 아이템의 인덱스를 얻어오는 간결한 문법을 제공range
로 루프를 실행하고 시퀀스에 인덱스로 접근하기보다는 enumerate
를 사용하는 게 좋다.enumerate
에 두 번째 파라미터를 사용하면 시작 넘버를 설정 할 수 있다(기본값 0)for i, seq in enumerate(sequence, 1): # i: 1 ~ len(seqeunce)
# someting....
zip
은 여러 이터레이터를 병렬로 순회할 때 사용할 수 있다.zip
은 튜플을 생성하는 lazy generator
이다. 파이썬 2의 zip
은 전체 결과를 튜플 리스트로 반환한다. (eger loading
)zip
은 그 결과를 조용히 잘라낸다.itertools
의 zip_longest
함수를 쓰면 이터레이터 길이에 상관없이 병렬로 순회 할 수 있다.else
블록을 둘 수 있다. else
는 루프문이나 try/except
구문에 사용 할 수 있는데, 루프가 정상적으로 수행이 끝나거나(break
문 없이), try
가 성공적으로 동작 했을 때 수행된다.else
블록을 사용하면 직관적이지 않고 혼동하기 쉬우니 피하자try/fianlly
구문을 사용하면 예외 발생 여부와 상관없이 정리 코드(리소스 해제 등)를 실행 할 수 있다.else
블록은 try
블록의 코드가 성공적으로 실행 된 후 실행되며, try
블록 코드 양을 최소로 줄이는데 도움을 준다.