본문 바로가기
BoostCamp AI Tech - U Stage

BoostCamp AI Tech - Day03

by getamped 2021. 1. 20.

오늘자 세션은 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

댓글