본문 바로가기
코딩 연습/코딩배우기

파이썬 실천 기술 #02 - 데이터 구조

by good4me 2021. 5. 20.

goodthings4me.tistory.com

효율적 개발로 이끄는 파이썬 실천 기술 - 데이터 구조

(참고용으로 사용할 부분만 간략하게 정리)

# None
d = {'a': 1, 'b': 2}
print(d.get('b'))
print(d.get('c'))  # get() 메서드는 값이 없으면 None 리턴됨으로 None이 보임.
print(d.get('c', '없음'))  # 디폴트 값을 줘서 None 대신 출력하도록 할 수 있음

[결과]
2
None
없음
# bool - 논리값(참/거짓) 다루는 타입
print(type(True), type(False))
print(bool(0), bool(None), bool([]), bool('book'), bool('0'))

[결과]
<class 'bool'> <class 'bool'>
False False False True True
x = ['book']
y = []
z = 0

print(x or y, y or x)  # or는 참인 것에 따름, x가 참이므로 x 반환
print(x and y, y and x)  # and는 좌가 참이면 우측, 거짓이면 좌측 따름, y가 거짓이므로 y 반환 
print(y and z, z and y)  # 둘 다 거짓, and 우측에 따름

[결과]
['book'] ['book']
[] []
[] 0
# 숫자 리터럴 입력할 때 언더스코어(_) 넣어 쓰기
print(1000000)
print(1,000,000)  # print()에서 콤마(,) 사용
print(1_000_000)  # '_'는 숫자에 영향주지 않음

[결과]
1000000
1 0 0
1000000
# float 타입과 무한대 - 양의 무한대 float('inf'), 음의 무한대 float('-inf')
print(float('inf'))
print(float('inf') + 10000)
print(float('-inf'))
print(type(float('inf')))

[결과]
inf
inf
-inf
<class 'float'>
# NaN(not a number)도 float 타입으로 두룬다
nan = float('nan')
print(nan)
print(type(nan))

[결과]
nan
<class 'float'>
# float 타입끼리의 연산, round() 함수로 반올림
print(0.1 + 0.1 + 0.1 == 0.3)  # False
print(round(0.1 + 0.1 + 0.1, 1) == round(0.3, 1))  # True

[결과]
False
True
# 문자열 다루는 str 타입
b = 'book'  # 문자열 리터러시
print(type(b))

# 문자열 안에서 줄바꿈은 \n 입력
nb = 'note\nbook'
print(nb)

[결과]
<class 'str'>
note
book
# '괄호'로 감싼 여러 연속 문자열은 한 개의 문자열로 간주 (URL 등 긴 문자열 정의에 편리)
URL = ('http://www.yes24.com/searchcorner/Search?keywordAd=&keyword=&domain=ALL'
'&qdomain=%C0%FC%C3%BC&query=%C6%C4%C0%CC%BD%E3+%BD%C7%C3%B5+%B1%E2%BC%FA')

print(URL)

[결과]
http://www.yes24.com/searchcorner/Search?keywordAd=&keyword=&domain=ALL&qdomain=%C0%FC%C3%BC&query=%C6%C4%C0%CC%BD%E3+%BD%C7%C3%B5+%B1%E2%BC%FA
# for 문에서 문자열은 이터러블 객체이고 한 문자씩 반환됨
for ch in 'book':
    print(ch)
    
[결과]
b
o
o
k
# f-string : 식을 삽입({} 이용)할 수 있는 '포맷 문자열 리터럴'(파이썬 3.6에서 추가)
title = 'book'
print(f'python practice {title}')
for k, v in enumerate('book', 1):
    print(f'{k}번째 {v}')

[결과]
python practice book
1번째 b
2번째 o
3번째 o
4번째 k
# 파이썬 3.8에서 {}로 감싼 변수나 식에 '='를 붙여, 평가 결과와 동시에 그 변수나 식을 문자열로 표시 (디버그 시 변수 값 확인 시 유용함)
title = 'sketchbook'
note = 'note'
print(f'title = {title}, note = {note}')  # 3.7에서
print(f'{title=}, {note=}')  # 3.8에서

[결과]
title = sketchbook, note = note
title='sketchbook', note='note'
# str.format() - 인수에 전달한 변수로 문자열 치환
for k, v in enumerate('book', 1):
    print('{}번째 {}'.format(k, v))  # {0}번째 {1} 인수의 위치

# {key}처럼 인수의 키워드를 전달 
print('python {p} {b}'.format(p='book', b='practice'))

# format() 메서드의 인수에 **와 함께 딕셔너리를 전달
d = {'x': 'note', 'y': 'notebook', 'z': 'sketchbook'}
books = '{x} {z}'
print(books.format(**d))

# 공식문서에서 % 연산자의 이용은 가급적 피하도록 권장

[결과]
1번째 b
2번째 o
3번째 o
4번째 k
python book practice
note sketchbook
# bytes 타입 - str 타입과 유사, 컴퓨터가 다루기 쉬운 바이트열
# str과 bytes는 서로 변환 가능 - str.encode() 와 bytes.decode()
book = '파이썬 실천 기술'
print(type(book))  # <class 'str'>

# UTF-8을 지정해서 인코딩
encoded = book.encode('utf-8')
print(type(encoded))  # <class 'bytes'> bytes로 인코드 됨
print(encoded)

# 디코딩
print(encoded.decode('utf-8'))

[결과]
<class 'str'>
<class 'bytes'>
b'\xed\x8c\x8c\xec\x9d\xb4\xec\x8d\xac \xec\x8b\xa4\xec\xb2\x9c \xea\xb8\xb0\xec\x88\xa0'
파이썬 실천 기술
# list 타입 - 변경할 수 있는 배열을 다루는 타입

items = ['note', 'book', 'sketchbook']
print(type(items))

item = list('book')
print(item)

# 엘리먼트 추가, 삭제
items.append('paperbook')
print(items)
item.append('s')
print(item)
del items[1]  # del dict[index]
print(items)

# 인덱스, 슬라이스를 이용한 접근
print(items[0])
print(items[:2])

[결과]
<class 'list'>
['b', 'o', 'o', 'k']
['note', 'book', 'sketchbook', 'paperbook']
['b', 'o', 'o', 'k', 's']
['note', 'sketchbook', 'paperbook']
note
['note', 'sketchbook']
# tuple 타입 - 변경할 수 없는 배열 타입(주로 애플리케이션 안에서의 설정값 지정 시 이용)
items = ('note', 'book', 'sketchbook')
print(items)

item = ('book')
print(type(item))

# tuple 만들기 방법
t = ()
print(type(t))

tu = 'note', 'book', 'sketchbook'
print(type(tu))

tup = 1,
print(type(tup))

tupl = tuple('book')
print(type(tupl), tupl)

# 인덱스, 슬라이스를 이용한 접근
print(items[0])
print(items[:2])

[결과]
('note', 'book', 'sketchbook')
<class 'str'>
<class 'tuple'>
<class 'tuple'>
<class 'tuple'>
<class 'tuple'> ('b', 'o', 'o', 'k')
note
('note', 'book')
# 딕셔너리(dictionary) -  키를 인덱스로 이용해서 저장된 값 추출
d = {}
print(type(d))

items = {'note': 1, 'notebook': 2, 'sketchbook': 3}
print(type(items))

print(items['note'])  # key로 value 추출

items['book'] = 4  # 새로운 키 지정해 값 추가
print(items)

print(items.pop('notebook'))  # dict.pop(key)으로 엘리먼트 삭제, 삭제된 값 반환
print(items)

del items['book']  # 객체 삭제
print(items)

# 존재하지 않는 키를 사용할 경우 에러 발생함(dict.get() 사용해 에러 방지할 수 있음)
print(items.get('book', 0))  # 기본값 0은 변경 가능

# 딕셔너리의 키는 문자열, 숫자값, 튜플 등 변경할 수 없는 객체만 이용할 수 있다
b = ['book']
#print({b: 1})  # TypeError: unhashable type: 'list'

print(items.keys(), type(items.keys()))  # 키 목록만 필요할 때
print(items.values(), type(items.values()))  # 값 목록만 필요할 때
print(items.items(), type(items.items()))  # 키와 값 목록이 필요할 때

[결과]
<class 'dict'>
<class 'dict'>
1
{'note': 1, 'notebook': 2, 'sketchbook': 3, 'book': 4}
2
{'note': 1, 'sketchbook': 3, 'book': 4}
{'note': 1, 'sketchbook': 3}
0
dict_keys(['note', 'sketchbook']) <class 'dict_keys'>
dict_values([1, 3]) <class 'dict_values'>
dict_items([('note', 1), ('sketchbook', 3)]) <class 'dict_items'>
# set 타입 - 변경할 수 없는 집합으로 엘리먼트 중복 불허, 순서 없음(index 이용 접근 불가)
print(type({}), type(set()))  # set 타입도 {}를 사용하나, 빈 {}는 dict이고, 빈 set은 set()으로 해야 함 
items = {'note', 'notebook', 'sketchbook', 'sketchbook'}
print(items)  # 중복 배제

# 추가 삭제
items.add('book')
items.add('paperbook')
items.remove('note')  # set.remove() 지정 삭제
print(items)
items.pop()  # set.pop(): 순서가 없어서 엘리먼트 지정 불가
print(items)

# set 집합 연산
# 합집합 set_a.union(set_b) => set_a | set_b
# 교집합 set_a.intersection(set_b) => set_a & set_b
# 차집합 set_a.difference(set_b) => set_a - set_b
# 기타 symmetric_defference(), issubset()

[결과]
{'sketchbook', 'notebook', 'note'}
{'paperbook', 'book', 'notebook', 'sketchbook'}
{'book', 'notebook', 'sketchbook'}
# frozenset 타입 - 변경할 수 없는 집합 타입, 리터럴은 미 제공
items = frozenset()
print(items, type(items))
items = frozenset(['note', 'notebook'])  # frozenset({'note', 'notebook'})
print(items)
#print(items.add('book'))  # 'frozenset' object has no attribute 'add'

[결과]
frozenset() <class 'frozenset'>
frozenset({'notebook', 'note'})
# 컴프리헨션(comprehension) - 리스트, 딕셔너리, 집합 등을 만들 수 있는 특별한 구문
# [리스트 엘리먼트 for 변수 in 이터러블 객체] => 변수의 스코프도 컴프리헨션 내임
numbers = []
for i in range(10):
    numbers.append(str(i))
print(numbers)

lst = [str(v) for v in range(10)]
print(lst)

tps = []
for x in [1, 2, 3]:
    for y in [4, 5, 6]:
        tps.append((x, y))
print(tps)

tps_comp = [(x, y) for x in [1, 2, 3] for y in [4, 5, 6]]
print(tps_comp)

# if 문이 있는 컴프리헨션
even = []
for i in range(10):
    if i % 2 == 0:
        even.append(i)
print(even)

lst_if = [x for x in range(10) if x % 2 == 0]
print(lst_if)

[결과]
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]
[0, 2, 4, 6, 8]
[0, 2, 4, 6, 8]
# 리스트 컴프리헨션 []를 {}로 변경 => set 컴프리헨션
set_comp = {i for i in range(10)}
print(type(set_comp), set_comp)

# 리스트 컴프리헨션 []를 {}로 변경하고 key: 값 추가 => dict 컴프리헨션
dict_comp = {str(x): x for x in range(3)}
print(type(dict_comp), dict_comp)

# 리스트 컴프리헨션 []를 ()로 변경 => 이터레이터 객체를 생성하는 제너레이터 식이 됨
gen = (n for n in range(3))
print(type(gen), gen)

[결과]
<class 'set'> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
<class 'dict'> {'0': 0, '1': 1, '2': 2}
<class 'generator'> <generator object <genexpr> at 0x7f513be2ea50>
- 가변객체(mutable) : 정의 후 값을 변경할 수 있는 객체, list, dict, set
- 불변객체(immutable) : 정의 후 값을 변경할 수 없는 객체, int, float, str, tuple, frozenset
- 컨테이너 객체 : list, dict,set 등 다른 객체의 참조를 가진 객체(인덱스로 접근할 수 있는 시쿼스 객체와 키로 접근하는 매핑 객체)

 

[참고/출처] 효율적 개발로 이끄는 파이썬 실천 기술 - 파이썬에 숨겨진 힘을 이용해 개발 효율을 높이자!

댓글