오늘자 세션은 Python Data Structure, Pythonic code이었다. Java를 위주로 쓴 본인에겐 Data Structure는 들어봤지만, Pythonic code는 처음이었다. 따라서, 세션에서 들었던 지식을 이곳에 남겨보고자 한다.
1. 스택
2. 큐
3. 튜플(tuple)
4. 집합(Set)
5. 사전(Dictionary)
5-1. 정의
- 데이터를 저장 할 때는 구분 지을 수 있는 값을 함께 저장
- 구분을 위한 데이터 고유 값을 Identifier 또는 Key라고 함
- Key 값을 활용하여, 데이터 값(Value)를 관리함
5-2. 특징
- key와 value를 매칭하여 key로 value를 검색
- 다른 언어에서는 Hash Table이라는 용어를 사용
- {Key1:Value1, Key2:Value2, Key3:Value3...}형태
- 예시
student_info={20140012:'ShinChan',20140059:'Chulsu',20140058:'Yuri'}
student_info[20140012]
student_info[20140012]='MaengGu'
student_info[20140012]
student_info[20140039]='Hunni'
studnet_info
- 결과
| Key | Value |
| 20140012 | MaengGu |
| 20140059 | Chulsu |
| 20140058 | Yuri |
| 20140039 | Hunni |
- dict 생성
country_code={} # Dict 생성
# 또는
country_code=dict()
country_code={"America":1,"Korea":82,"China":86,"Japan":81}
- dict 데이터 출력
country_code.items()
- dict Value만 출력
- Key, Value 언패킹
for k,v in country_code.items():
print("Key : ",k)
print("Value : ",v)
6. Collections 모듈
- List, Tuple, Dict에 대한 Python Built-in 확장 자료 구조(모듈)
- 편의성, 실행 효율 등을 사용자에게 제공함
- 아래의 모듈이 존재함
from collections import deque
from collections import Counter
from collections import OrderedDict
from collections import defaultDict
from collections import namedtuple
6-1. deque
- Stack과 Queue를 지원하는 모듈(Module)
- List에 비해 효율적이고 빠른 자료 저장 방식을 지원함
- rotate,reverse 등 LinkedList(연결리스트)의 특성을 지원함
- 기존 list 형태의 함수를 지원함
- 효율적 메모리 구조로 처리속도 향상
from collections import deque
deque_list=deque()
for i in range(5):
deque_list.append(i)
print(deque_list)
deque_list.appendleft(10)
print(deque_list)
6-2. OrderedDict
- Dict와 달리, 데이터를 입력한 순서대로 dict를 반환함
- Python 3.6부터 dict도 입력한 순서를 보장하여 출력함
6-3. DefaultDict
- dict type의 값에 기본 값을 지정, 신규값 생성시 사용하는 방법
from collections import defaultdict
d=defaultdict(object)
d=defaultdict(lambda:0)
print(d["first"])
6-4. Counter
6-5. namedtuple
- Tuple 형태로 Data 구조체를 저장하는 방법
- 저장되는 data의 variable을 사전에 지정해서 저장함
from collections import named tuple
Point = namedtuple('Point',['x','y'])
p=Point(11,y=22)
print(p[0]+p[1])
x,y=p
print(x,y)
print(p.x+p.y)
print(Point(x=11,y=22))
Ⅱ. Pythonic Code
본인에게 Pythonic Code는 낯선 용어인데, 알고보니 '파이썬스럽게' 코드를 작성
1. Pythonic Code란?
- 파이썬 스타일의 코딩 기법
- 파이썬 특유의 문법을 활용하여 효율적으로 코드를 표현함
- 고급 코드를 작성할 수록 필요성이 대두됨
Pythonic Code가 필요한 이유
- 많은 Python 개발자들이 python 스타일로 코딩한다.
- 많은 Python 라이브러리(데이터 분석, AI 등)가 python 스타일로 이루어져 있다. 즉, 다른 사람이 개발한 코드를 이해하기 위함
- 단순 for loop내의 append보다, list가 좀 더빠르다. 익숙해지면 코드도 짧아진다.
-> 즉, 시간 효율성, 코드 가독성 면에서 장점이 있다.
2. Split & Join
-Pythonic한 코드의 기법 중에 split(잘게 나누기), join(각 원소를 합치기)이 있다.
2-1. split 함수
items="zero one two three"
items.split(" ")
# ['zero','one','two','three']
example="psk.boostcamp.io"
subdomain,domain,tld=example.split(".") #언패킹(unpacking)
# subdomain='psk', domain='boostcamp', tld='io'
2-2. Join 함수
colors=["red","blue","green","yellow"]
"_".join(colors)
# 'red-blue-green-yellow'
3. list comprehension
정의
- 기존 List를 사용하여 간단하게 다른 List를 만드는 기법
- 포괄적인 List, 포함되는 리스트라는 의미로 사용됨
- 파이썬에서 가장 많이 사용되는 기법 중 하나
- for loop 내의 append보다 속도가 빠르다.
General vs List comprehension
- 아래의 두 코드는 같은 결과값이 나온다.
# General
result=[]
for i in range(10):
result.append(i)
# result=[0,1,2,3,4,5,6,7,8,9]
# List Comprehension
result=[i for i in range(10)]
# result=[0,1,2,3,4,5,6,7,8,9]
또한, Nested For loop도 있다.
word_1="Hello"
word_2="World"
result=[i+j for i in word_1 for j in word_2]
'''
result=[
'HW','Ho','Hr','Hl','Hd','eW','eo','er',
'el','ed','lW','lo','lr','ll','ld','lW',
'lo','lr','ll','ld','oW','oo','or','ol','od'
]
'''
즉, word_1과 word_2의 원소가 합쳐져 result의 원소로 나오게 된 것이다.
아래와 같이 필터링(filtering)도 가능하다고 한다.
result=[i for i in range(10) if i%2==0]
# result=[0,2,4,6,8]
case_1=["A","B","C"]
case_2=["D","E","A"]
result = [i+j for i in case_1 for j in case_2]
# ['AD','AE','BD','BE','BA','CD','CE','CA']
[i+j if not(i==j) else "BEE" for i in case_1 for j in case_2]
# ['AD','AE','BEE','BD','BE','BA','CD','CE','CA']
# pprint(result)
※ pprint : list의 결과값을 세로로 출력하는 모듈
4. Two dimentional list
- 이차원 리스트를 Pythonic하게 구성함
words = "The quick brown fox jumps over the lazy dog".split()
# ['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']
pprint.pprint([[w.upper(),w.lower(),len(w)]for w in words])
'''
[['THE', 'the', 3],
['QUICK', 'quick', 5],
['BROWN', 'brown', 5],
['FOX', 'fox', 3],
['JUMPS', 'jumps', 5],
['OVER', 'over', 4],
['THE', 'the', 3],
['LAZY', 'lazy', 4],
['DOG', 'dog', 3]]
'''
case_1=["A","B","C"]
case_2=["D","E","A"]
result = [[i+j for i in case_1] for j in case_2]
# [['AD', 'BD', 'CD'], ['AE', 'BE', 'CE'], ['AA', 'BA', 'CA']]
5. enumerate
- enumerate : list의 element를 추출할 때 번호를 붙여서 추출
for i,v in enumerate("ABC"):
print(f"{i} \t {v}")
'''
0 A
1 B
2 C
'''
my_str="ABCD"
{v:i for i,v in enumerate(my_str)}
'''
{'A': 0, 'B': 1, 'C': 2, 'D': 3}
'''
text = "Samsung Group is a South Korean multinational conglomerate headquartered in Samsung town, seoul"
{i:v.upper() for i,v in enumerate(text.split())}
'''
{0: 'SAMSUNG',
1: 'GROUP',
2: 'IS',
3: 'A',
4: 'SOUTH',
5: 'KOREAN',
6: 'MULTINATIONAL',
7: 'CONGLOMERATE',
8: 'HEADQUARTERED',
9: 'IN',
10: 'SAMSUNG',
11: 'TOWN,',
12: 'SEOUL'}
'''
text = "Samsung Group is a South Korean multinational conglomerate headquartered in Samsung town, seoul"
set_text = list(set(text.split()))
{i:v.upper() for i,v in enumerate(set_text)}
'''
{0: 'MULTINATIONAL',
1: 'SOUTH',
2: 'SAMSUNG',
3: 'KOREAN',
4: 'A',
5: 'SEOUL',
6: 'GROUP',
7: 'CONGLOMERATE',
8: 'HEADQUARTERED',
9: 'TOWN,',
10: 'IN',
11: 'IS'}
'''
6. zip
- 두 개의 list의 값을 병렬적으로 추출함
alist=["a1","a2","a3"]
blist=["b1","b2","b3"]
[[a,b] for a,b in zip(alist,blist)]
# [['a1', 'b1'], ['a2', 'b2'], ['a3', 'b3']]
[c for c in zip(alist,blist)]
# [('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')]
math = (100,90,80)
kor = (90,90,70)
eng = (90,80,70)
[sum(value)/3 for value in zip(math,kor,eng)]
# [93.33333333333333, 86.66666666666667, 73.33333333333333]
- enumerate, zip 조합
alist=["a1","a2","a3"]
blist=["b1","b2","b3"]
for i,values in enumerate(zip(alist,blist)):
print(i,values)
'''
0 ('a1', 'b1')
1 ('a2', 'b2')
2 ('a3', 'b3')
'''
7. lambda
- 이름 없는 익명함수
- 수학의 람다 대수에서 유래
f=(lambda x,y:x+y)
f(10,50)
# 60
(lambda x,y : x+y)(10,50)
# 60
up_low=lambda x: "-".join(x.split())
up_low("My Happy")
# 'My-Happy'
그런데... Python 3부터는 권장하지 않으나, 여전히 많이 쓰인다고는 한다. PEP 8에서 람다보다 def를 사용하라고 권장하기 때문이라고 한다.
(이유 : 어려운 문법, 테스트의 어려움, 문서화 docstring 지원 미비, 코드 해석의 어려움, 이름 없는 함수 등)
8. Map
- 연속적인 데이터가 있을 때, 각 원소에 매핑(Mapping)하는 함수(function)
- 두 개 이상의 list에도 적용 가능함, if filter도 사용가능
※ Python 3부터는 itreation을 생성하면 list()을 적용해야 list를 사용할 수 있다.
- 실행시점의 값을 생성하므로 메모리 이용면에서 효율적이다.
ex = [1,2,3,4,5]
f=lambda x:x**2
list(map(f,ex))
# [1, 4, 9, 16, 25]
f=lambda x,y:x+y
list(map(f,ex,ex))
# [2, 4, 6, 8, 10]
list(map(lambda x:x**2 if x%2==0 else x,ex))
# [1, 4, 3, 16, 5]
[value**2 if value%2==0 else value for value in ex]
# [1, 4, 3, 16, 5]
9. reduce
- map function과 다르게 list에 똑같은 함수를 적용해서 통합
- Python 3에서 사용을 권장하지 않음(by. 공식문서)
from functools import reduce
reduce(lambda x, y:x+y,[1,2,3,4,5])
# 5
10. iterable object
- Sequence형 자료형에서 데이터를 순서대로 추출하는 object
- 내부적으로 _iter_와 _next_가 사용됨
11. generator
- iterable object를 특수한 형태로 사용해주는 함수
- element가 사용되는 시점에 값을 메모리에 반환
: yield를 사용해 한번에 하나의 element만 반환함
- 대용량을 활용할 때 이 함수를 사용하는 것을 권장
def gen_list(value):
result=[]
for i in range(value):
yield i
for a in gen_list(5):
print(a)
'''
0
1
2
3
4
'''
12. generator comprehension
- list comprehension과 유사한 형태로 generator형태의 list 생성
- generator expression이라는 이름으로도 부름
- [] 대신 ()를 사용하여 표현
gen_ex = (n*n for n in range(500))
print(type(gen_ex))
# <class 'generator'>
print(list(gen_ex))
# [0,1,4,9,16]
12-1. 왜 generator인가?
- 일반적인 iterator는 generator에 반해 훨씬 큰 메모리 용량 사용
from sys import getsizeof
gen_ex = (n*n for n in range(500))
print(getsizeof(gen_ex))
print(getsizeof(list(gen_ex)))
list_ex = [n*n for n in range(500)]
print(getsizeof(list_ex))
'''
112 # generator의 용량
4568 # list()를 붙인 generator
4264 # 일반 list
'''
12.2 generator가 쓰일 때
- list 타입의 데이터를 반환해주는 함수는 generator로 만든다.
: 읽기 쉬운 장점, 중간 과정에서 loop가 중단될 수 있을 때
- 큰 데이터를 처리할 때는 generator expression을 고려한다.
: 데이터가 커도 처리의 어려움이 없음
- 파일 데이터를 처리할 때도 generator를 쓴다.
'BoostCamp AI Tech - U Stage' 카테고리의 다른 글
| BoostCamp AI Tech - Day06 (0) | 2021.01.25 |
|---|---|
| BoostCamp AI Tech - Day05 (0) | 2021.01.22 |
| BoostCamp AI Tech - Day04 (0) | 2021.01.21 |
| BoostCamp AI Tech - Day02 (0) | 2021.01.19 |
| BoostCamp AI Tech - Day01 (0) | 2021.01.18 |
댓글