본문 바로가기
BOOSTCAMP AI TECH/1주차_Python Basics For AI

[BOOSTCAMP AI TECH] 3일차_파이썬 기초문법2

by 이민우 2021. 1. 20.
728x90
반응형
  • 강의 목록

-Python Data Structure

-Python code


  • 요약

강의

파이썬에서 사용할 수 있는 자료구조와, Collections에서 사용할 수 있는 자료구조들에 대해 학습했다.

 

피어세션

모더레이터의 발표 및 질의응답 형식을 통해 전날 받은 수업을 복습하는 시간을 가졌다.

또한 모더레이터의 코드를 기준으로 과제 풀이를 하며 더 나은 풀이방법을 깨닫는 시간을 가졌다.


  • 학습정리

스택 (Stack)

  • 마지막에 삽입한 데이터를 먼저 반환하도록 설계된 구조 (LIFO)
  • Data의 입력을 Push, 출력을 Pop이라고 한다.
  • 리스트를 사용해 스택 구조를 구현할 수 있다.
  • 리스트의 append()와 pop() 함수를 사용하여 구현 가능

 

(Queue)

  • 먼저 넣은 데이터를 먼저 반환하도록 설계된 구조 (FIFO)
  • Stack과 반대되는 개념
  • 리스트를 사용해 큐 구조를 활용할 수 있다.
  • 리스트의 append()와 pop(0)을 사용하여 구현 가능

 

튜플 (Tuple)

  • 값의 변경이 불가능한 리스트
  • 선언 시 [] 가 아닌 ()를 사용
  • 하나만 넣을경우 (1)이 아니라 (1, )로 할 것.
  • 리스트의 연산, 인덱싱, 슬라이싱 등을 동일하게 사용할 수 있다.
  • 변경되지 않은 데이터를 저장하여 사용자의 실수에 의한 에러를 사전에 방지하기 위해 사용된다.

 

집합 (Set)

  • 값을 순서없이 저장하고 중복을 불허하는 자료형
  • set 객체 선언을 이용해 객체를 생성하거나, {}를 활용해 생성할 수 있다.
  • 수학에서 사용하는 다양한 집합연산이 가능하다.
  • remove 함수는 존재하지 않은 것을 삭제할 경우 에러가 발생하지만 discard는 에러가 발생하지 않는다.
add 추가 discard 삭제
remove 삭제 clear 전체 삭제
update 수정 union 합집합
intersection 교집합 difference 차집합

 

사전 (Dict)

  • 데이터를 저장할 때 구분지을 수 있는 값과 함께 저장
  • 구분을 위한 데이터 고유값을 Identifier 또는 Key라고 한다.
  • Key 값을 활용해 데이터 값(Value)를 관리한다.
  • Key와 Value를 매칭하여 Key로 Value를 검색한다.
  • 다른 언어에서는 Hash Table이라는 용어를 사용한다.

 

Collections

  • List, Tuple, Dict에 대한 Python Built-in 확장 자료구조 (모듈)
  • 편의성, 실행 효율 등을 사용자에게 제공한다.

 

collections.deque()

  • Stack과 Queue를 지원하는 모듈
  • List에 비해 빠른 자료 저장 방식을 지원함.
  • rotate, reverse 등 Linked List의 특성을 지원함
  • 기존 List 형태의 함수를 모두 지원함.
  • 효율적 메모리 구조로 처리 속도 향상
#--deque--#
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)
deque_list.extend([1,2,3]) #extendleft도 있음.
print(deque_list)

#삭제
print(deque_list.pop())
print(deque_list)
print(deque_list.popleft())
print(deque_list)

#회전
deque_list.rotate(2) #파라미터만큼 회전
# 12345=>rotate(2)=>34512 만약 음수면 반대로 회전
print(deque_list)

 

collections.OrderedDict()

  • 데이터를 입력한 순서대로 dict 반환
  • 원래 dict는 입력한 순서를 보장하지 않았으나 3.6부터 순서 보장한다.
  • dict type 값을 value 또는 key 값으로 정렬할 때 사용 가능
#--ordereddict--#
from collections import OrderedDict
d = OrderedDict({'a':100, 'c':200, 'b':300, 'd':400})
print(d) #OrderedDict([('a', 100), ('c', 200), ('b', 300), ('d', 400)])

#반환
#True : LIFO / False : FIFO
d.popitem(True)
print(d) #OrderedDict([('a', 100), ('c', 200), ('b', 300)])
d.popitem(False)
print(d) #OrderedDict([('c', 200), ('b', 300)])

#이동
#True : 맨 오른쪽으로 / False : 맨 왼쪽으로
d.move_to_end('c', True)
print(d) #OrderedDict([('b', 300), ('c', 200)])
d.move_to_end('c',False)
print(d) #OrderedDict([('c', 200), ('b', 300)])

#키값 정렬
for k,v in OrderedDict(sorted(d.items(), key=lambda t:t[0])).items():
    print(k, v)
print('---------')
#밸류값 정렬
for k, v in OrderedDict(sorted(d.items(), key=lambda t: t[1])).items():
    print(k, v)

 

collections.defaultdict()

  • dict type 값에 기본 값을 지정하여 신규값 생성시 사용
  • dict에도 dict.setdefault()가 있다. 하지만 defaultdict가 훨씬 간단하고 빠르다.
#--defaultdict--#
from collections import defaultdict
d = defaultdict()
d = defaultdict(lambda : 0) #디폴트 값을 0으로 설정
print(d["a"])
print(d) #별도로 추가하지 않았음에도 자동으로 추가됨

 

collections.Counter()

  • sequence type의 data element들의 개수를 dict 형태로 반환
  • dict type, keyword parameter 등도 모두 처리 가능
  • set 연산들도 지원
#--counter--#
from collections import Counter
stri = 'abcsddsfgdbd'
c = Counter(stri)
print(c)

stri = ['abc', 'vca', 'bsd', 'abc']
c = Counter(stri)
print(c)

c = Counter(a=4, b=3, c=2, d=1, e=0)
print(c) #Counter({'a': 4, 'b': 3, 'c': 2, 'd': 1, 'e': 0})

c.update({'a':3, 'z':10}) #원래 있는거는 더하고 없던거는 추가
print(c) #Counter({'z': 10, 'a': 7, 'b': 3, 'c': 2, 'd': 1, 'e': 0})

d = dict(c) #dict로 변환
print(d) #{'a': 7, 'b': 3, 'c': 2, 'd': 1, 'e': 0, 'z': 10}

#원소 보기
print(list(c.elements())) #['a', 'a' ... 'z', 'z']
#많은 순서대로
print(c.most_common()) #[('z', 10), ('a', 7), ('b', 3), ('c', 2), ('d', 1), ('e', 0)]
print(c.most_common(3)) #3개만 [('z', 10), ('a', 7), ('b', 3)]

#set 연산도 지원
c = Counter(a=4, b=3, c=2, d=1, e=0)
d = Counter(a=1, b=2, c=3, d=4, e=5)
c.subtract(d) #원소별로 빼기
print(c)
c += d
print(c) #원소별로 더하기. 0이 되면 사라지네.       
print(c&d) #겹치는 키 중 작은 값 ({'b': 2, 'c': 2, 'a': 1, 'd': 1})
print(c|d) #모든 키 중 큰 값({'e': 5, 'a': 4, 'd': 4, 'b': 3, 'c': 3})

 

collections.namedtuple

  • Tuple 형태로 data 구조체를 저장하는 방법
  • 저장되는 데이터 변수를 사전에 지정해서 저장한다.
#--namedtuple--#
from collections import namedtuple
Point = namedtuple('Point', ['x','y'])
p = Point(11, 22)
print(p) #Point(x=11, y=22)
print(p[0]+p[1]) #33
print(Point(11, 22)) #Point(x=11, y=22)

#이렇게 생성 가능
p2 = Point._make([10,20]) 
print(p2) #Point(x=10, y=20)

#OrderedDict로 변환
print(p2._asdict) #<bound method Point._asdict of Point(x=10, y=20)>

#수정
p2 = p2._replace(x=30)
print(p2) #Point(x=30, y=20)

#필드명 출력
print(p2._fields) #('x', 'y')

#dict to namedtuple
dic = {'x':3, 'y':5}
p3 = Point(**dic)
print(p3) #Point(x=3, y=5)

 

 

파이썬 스타일 코드

  • 파이썬은 특유의 문법을 활용하여 효율적으로 코드를 표현한다.

*더 이상 파이썬 특유는 아님. 많은 언어들이 서로의 장점을 채용했기 때문.

 

Split&Join

#--Split&Join--#
stri = "hi my name is lmw"
striSpl = stri.split()
print(striSpl) #['hi', 'my', 'name', 'is', 'lmw']
stri = '-'.join(striSpl)
print(stri) #hi-my-name-is-lmw

 

List comprehension

  • 기존 리스트로 다른 리스트를 만드는 방법
  • 포괄적인 리스트, 포함되는 리스트 라는 의미로 사용
  • 파이썬에서 많이 사용되고, for+append 보다 빠르다.
#--List Comprehension--#
l = [i for i in range(10)]
print(l)
l = [i for i in range(10) if i%2 == 0] #else도 가능
print(l)
word1 = 'hello'
word2 = 'world'
l = [i+j for i in word1 for j in word2]
print(l)
word1 = ['a','b','c']
word2 = ['d','e','f']
l = [i+j for i in word1 for j in word2]
print(l)

 

enumerate&zip

  • enumerate : list의 원소를 추출할 때 번호를 붙여서 추출
  • zip : 두 개의 list 값을 병렬적으로 추출
#--enumerate & zip--#
for i, v in enumerate(['z','s','q']) : print(i, v)
myl = list(enumerate(['z','s','q']))
print(myl) #[(0, 'z'), (1, 's'), (2, 'q')]

word1 = ['a','b','c']
word2 = ['d','e','f']
for a,b in zip(word1, word2) : print(a,b)
a,b,c = zip(word1, word2)
print(a,b,c) #('a', 'd') ('b', 'e') ('c', 'f') 튜플 타입으로 묶어줌

 

Lambda

  • 함수의 이름 없이 함수처럼 쓸 수 있는 익명함수
  • 문법, 테스트, 해석이 어려움, 그리고 문서화 docsting 지원이 미비하다.
  • Python 3부터는 권장하지 않으나 아직 많이 사용됨 (PEP8도 권장하지 않음)
#--lambda--#
f = lambda x,y : x+y
print(f(1,4))

 

Map Function

  • 두 개 이상의 list에도 적용이 가능하고, if filter도 사용이 가능하다.
  • python3는 iteration을 생성하기에 list를 붙여줘야 list 사용이 가능하다.
  • 실행시점의 값을 생성효율적으로 메모리를 사용한다.
#--map--#
ex = [1,2,3,4,5]
f = lambda x, y: x+y
print(list(map(f,ex,ex)))  #[2,4,6,8,10]
print(list(map(lambda x:x**2 if x%2 ==0 else x, ex))) #[1, 4, 3, 16, 5]

 

Reduce Function

  • Map Function과 달리 list에 똑같은 함수를 적용하여 통합한다.
  • Map처럼 list로 만드는 것이 아닌, 원소를 하나씩 줄여가며 통합
  • Lambda, map, reduce는 간단한 코드로 다양한 기능을 제공한다.
  • 하지만 lambda와 마찬가지로 코드의 직관성이 떨어져 권장하지 않는다.
  • Legacy Library나 다양한 머신러닝 코드에서는 여전히 사용중.
#--reduce--#
from functools import reduce
print(reduce(lambda x, y: x+y, ex)) #15

 

Iterable object

  • 연속형 자료형에서 데이터를 순서대로 추출하는 객체
  • 내부적 구현으로 __iner__와 __next__가 사용됨
  • iter()과 next() 함수로 iterable 객체를 iterator object로 사용
#--inerable object--#
cities = ["Seoul", "Busan","Jeju"]
iter_obj = iter(cities)
print(next(iter_obj)) #Seoul
print(next(iter_obj)) #Busan
print(next(iter_obj)) #Jeju
#next(iter_obj) #error

 

Generator

  • iterable object를 특수한 형태로 사용해주는 함수
  • element가 사용되는 시점에 값을 메모리에 반환
  • yeild를 사용하면 한 번에 하나의 element를 반환
  • yield from (리스트명) 을 하면 굳이 포문으로 돌리지 않아도 된다.
  • 일반적인 iterator는 generator에 반해 훨씬 큰 메모리 용량을 사용한다.
  • list 타입의 데이터를 반환해주는 함수는 generator로 만들면 읽기가 쉽고, 도중에 중단이 가능하다.
  • 데이터가 커도 처리의 어려움이 없어 큰 데이터 처리시 사용
  • 파일 데이터 처리에도 사용하면 좋다.
#--Generator--#
def general_list(value) :
    result = []
    for i in range(value) : result.append(i)
    return result

print(general_list(5))

#yield를 사용하면 한 번에 하나의 element 반환
def generator_list2(value) :
    result = []
    for i in range(value) : yield i
a,b,c,d,e = general_list(5)
print(a,b,c,d,e)

 

 

Generator Comprehension

  • list comprehension과 유사한 형태로 generator 형태의 list 생성
  • generator expression이라는 이름으로도 부름
  • []대신 ()을 사용해 표현한다.
#--Generator Comprehension--#
gen_ex = (n*n for n in range(10))
print(type(gen_ex))

 

Iterator와 Generator의 차이점
-Generator는 Iterator를 생성해주는 함수이다.
 Iterator란 next()함수를 통해 순차적으로 호출이 가능한 객체인데, generator는 함수 내부에서
 yield를 통해 iterator를 생성해주는 함수이다.

Generator가 메모리 측면에서 더 효율적인 이유?
-일반함수의 경우 함수 내부의 구문 실행 후 마지막 return으로 함수가 종료된다.
 하지만 generator는 yield를 통해 iterator를 반환하고 그 시점에서 일시정지 후 다음 next 호출을 기다린다.
 즉, 필요할 때만 메모리를 반환받아 사용하기에 메모리 측면에서 효율적이다.
 데이터가 큰 경우 루프보다 제너레이터를 사용하는 것이 좋다.

 

 

Function passing arguments

  • 함수에 입력되는 argument는 세 가지 형태가 있다.

1) Keyword argument

  • 함수에 입력되는 파라미터의 변수명을 사용해 argument를 넘김

2) Default argument

  • 파라미터의 기본 값을 사용해 미입력시 기본값 출력
  • default argument는 가능한 뒤로 뺀다.

3) Variable-length argument (가변인자)

-Varuable length (가변인자)

  •  함수의 파라미터가 정해지지 않은 경우 사용
  •  개수가 정해지지 않은 변수를 함수의 파라미터로 사용하는 법
  •  Keyword arguments와 함께 argument 추가가 가능하다.
  •  Asterisk(*) 기호를 사용해 함수의 파라미터를 표시
  •  입력된 값은 tuple type으로 사용할 수 있다.
  •  가변인자는 오직 한 개만 맨 마지막 파라미터 위치에 사용가능하다.
  •  가변인자는 일반적으로 *args를 변수명으로 사용한다.
  •  기존 파라미터 이후에 나오는 값을 튜블로 저장한다.

-Keyword variable-length (키워드 가변인자)

  •  파라미터 이름을 따로 지정하지 않고 입력
  •  Asterisk(*) 두 개를 사용해 함수의 파라미터에 표시 (dict값으로 넘어감)
  •  입력된 값은 dict type으로 사용할 수 있다.
  •  가변인자는 오직 한 개만 기존 가변인자 다음에 사용한다.
#--Parameter&Argument--#
def print_name(name, age=0) :
    print("{}, {}".format(name, age))

print_name(name = 'lmw', age = 27) #KeyWord argument
print_name(name = 'lmw') #Default arhument

#Variable-length asterisk
def print_info(name, age, *etc, **language) :
    print('basic info : ', name, age)
    print('variable length : ', etc)
    print('keyword variable length : ', language)
    print('keyword variable length : {language1},{language2},{language3}'.format(**language))

print_info('lmw',27,'경기도','허허',language1 = 'JAVA', language2 = 'Python', language3 = 'JavaScript')

 

Asterisk (*)

  • 단순 곱셈, 제곱연산, 가변인자 활용 등 다양하게 사용된다.
  • tuple, dict 등 자료형에 들어간 값을 언패킹할 때 사용
  • 함수의 입력값, zip 등에 유용하게 사용가능
#--Asterisk--#
def asterisk_test(a, *args) :
    print(a, args, type(args))

#어떻게 넣어도 무조건 튜플로 들어감 : 불변
asterisk_test(1,(1,2,3)) #1 ((1, 2, 3),) <class 'tuple'>
asterisk_test(1,[1,2,3]) #1 ((1, 2, 3),) <class 'tuple'>
asterisk_test(1,{1,2,3}) #1 ((1, 2, 3),) <class 'tuple'>

#자연스럽게 언패킹됨.
data = (1,2,3)
print(*data)
data = ([1,2],[3,4],[5,6])
print(*data)

for d in zip(*data) : print(d)

 

 

*오늘의 TIP

-Jupyter Notebook에서 Tab키를 누르면 가용한 함수 리스트가 나옴


  • 피어세션 회의 내용

-


  • 해야할 일

파이썬에 대한 이해도가 많이 낮았음을 알게해준 강의였다.

아직 모르는 모듈들과 함수, 자료구조들이 많이 존재했고, 이에 대해 각 자료구조의 심화 개념과 응용법을 다져야 할 필요성이 느껴졌다.

 

참고

excelsior-cjh.tistory.com/98?category=966334

 


 

728x90
반응형