Python의 자료형 & Pythonic code

오늘배운 내용들은 굉장히 방대하다

1. 자료구조

특징이 있는 정보를 어떻게 저장하면 좋을까?

기본데이터 구조

  • 스택과 큐
  • 튜플과 집합
  • 사전 (dictionary)
  • Collection 모듈

1-1) Stack

스택이란?

나중에 들어온 데이터를 먼저 반환하도록 설계된 메모리 구조

LIFO (Last In First Out)

Data의 입력 : Push

Data의 출력 : Pop

Stack with list object

  • append()와 pop()을 사용하여 리스트로 스택을 구현가능

a.pop() 이라는 함수는 return이 존재하고 a 도 변화시켜줌

1-2) Queue

Queue란?

먼저들어온 데이터를 먼저 반환하도록 설계된 메모리 구조

FIFO(First in First out)

Queue with list object

  • append()와 pop(0)를 사용하여 리스트로 큐를 구현가능

1-3) Tuple

Tuple이란?

  • 값의 변경이 불가능한 리스트
  • 선언시 [] 가 아닌 ()를 사용
  • tuple의 요소에 인덱스로 접근하여 변경시도시 오류 발생(할당이 안된다)

왜쓸까?

  • 프로그램 작동중 변경되면 안되는 데이터를 저장할때 사용
  • ex) 학번 우편번호 이름 ….
  • 사용자의 실수에 의한 에러를 방지함

(1)의 타입은 int

tuple로 만들고 싶다면 (1,)라고 선언해주어야 함

1-4) Set

Set이란?

  • 값을 순서없이 저장, 중복이 안됨
  • set 객체의 선언으로 구현가능
1
2
3
s = set([1,2,3,4,1,2,3,4])
s = {1,2,3,1,2,3,4}
#이런식으로 선언을 하면 중복이 사라짐

remove(), add(), update(), discard()로 값 수정가능

Set의 연산

1
2
3
4
5
6
7
8
9
10
11
s1 = set([1,2,3,4,5])
s2 = set([3,4,5,6,7])

s1.union(s2)
s1 | s2 # s1과 s2의 합집합

s1.intersection(s2)
s1 & s2 # s1과 s2의 교집합

s1.difference(s2)
s1 - s2 #s1과 s2의 차집합

1-5) Dict

사전 (dictionary) 란?

  • 데이터를 저장할 때 데이터를 구분지을 수 있는 값을 함께 저장

  • 구분을 위한 데이터 값 : key

  • key값을 활용하여, value를 관리함

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
c = {"a" : 1, "b" :2}
c.items() # tuple의 형태로 key와 value값들이 나옴

c.values() # dict의 value값만이 list로 나옴
c.keys() #dict의 key값만이 list로 나옴
c["c"] = 3 # dict에 추가

"k" in c
#false
"a" in c
#true

for k,v in c.items():
print(k)
print(v)

1-6) Collections

  • List, Tuple, Dict를 파이썬에서 모듈로 지원해줌

1-6-1) Deque

  • queue와 stack을 동시에 지원함
  • List에 비해 시간복잡도가 낮아 빠름 (pop이 시간복잡도가 낮음)
  • append()
  • appendleft()

Linked list의 특성을 지원함

기존의 list함수들도 모두 지원함

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from collections import deque

d = deque()
for i in range(5):
d.append(i)
#d = deque([0,1,2,3,4])

d.appendleft(10)
# d = deque([10,0,1,2,3,4])

d.rotate(1)
# d = deque([4,10,0,1,2,3])

d.extend([1,2,3])
# d = deque([4,10,0,1,2,3,1,2,3])

1-6-2) Ordered dict

Dict와 달리 데이터를 입력한 순서대로 dict를 반환함

그러나 지금은 별로 의미가 없음

1-6-3) Default Dict

1
2
3
4
5
6
7
8
9
10
d = dict()
print(d["first"])
#error 발생
#이럴때 default를 주면 됨

from collections import defaultdict

d = defaultdict(lambda : 0)
d["first"]
# 0
  • ex) 하나의 지문에 몇개의 단어가 나오는지 세고 싶은 경우
1
2
3
4
from collections import defaultdict
d = defaultdict(lambda : 0)
for word in text:
d[word]+=1

1-6-4) Counter

  • Sequence type의 data element들의 갯수를 dict의 형태로 반환
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from collections import Counter

c = Counter()
c = Counter('gallahad')
print(c)
# Counter('a':3, 'l':2, 'g' : 1, 'd' : 1, 'h' : 1)

c = Counter({'red':4,'blue' : 2})
print(c)
# Counter('red': 4, 'blue' : 2)
print(list(c.elements()))
# ['blue','blue','red','red','red','red']

c = Counter(dogs = 10, cats = 8)
print(c)
# Counter('dogs':10,'cats':8)
print(list(c.elements()))'
# ['dogs','dogs','dogs','dogs','dogs','dogs','dogs','dogs','dogs','dogs',...,'cats']
#Set의 연산들을 지원함
c1 = Counter('allis')
c2 = Counter('paul')
print(c1-c2)
print(c1.subtract(c2))
# Counter('a' : 0, 'l' : 1, 'i':1,'s' :1, 'p' : -1, 'u' : -1)
print((c1-c2)['a'])
#0

1-6-5) Namedtuple

  • tuple의 형태로 Data 구조체를 저장하는 방법
  • 저장되는 data의 variable을 사전에 지정해서 저장함
1
2
3
4
5
from collections import namedtuple

Point = namedtuple('Point', ['x','y'])
p = Point(x = 11, y = 22)
p[0], p[1]

2. Pythonic code

  • 파이썬 스타일의 코딩 기법
  • 파이썬 특유의 문법을 사용하여 효율적으로 코드를 표현함
  • 많은 코드들의 장점을 채용함
  • 고급코드 작성시 많이 필요함

ex)

1
2
colors = ['red','blue','green']
result = ''.join(colors)
  • split, join
  • list comprehension
  • enumerate, zip
  • lambda, map, reduce
  • generateor
  • asterisk

왜 쓸까?

  • 남들의 코드를 이해하기 위해
  • 효율 : 단순 for loop보다 list가 더 빠르다
  • 쓰면 간지난다

2-1) Split & Join

**string type값을 기준값으로 나눠서 List 로 return **

ex) split

1
2
ex = "python, java, javascript"
p, j, js = ex.split(,) #unpacking

ex) join

1
2
3
ex =  ['python', 'java', 'javascript']
s = '-'.join(ex)
#s = 'python-java-javascript'

2-2) List Comprehension

  • 기존 리스트를 사용하여 새로운 리스트를 만든다
  • 파이썬에서 가장많이 사용된다
  • for + append 보다 빠르다

ex)

1
2
result = [i for i in range(5) if i%2==0]
#result = [0,2,4]

ex)

1
2
3
4
5
word1 = "hello"
word2 = "world"

result = [i+j for i in word1 for j in word2]
# result = ['hw','ho','hr'....., 'od']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
case_1 = ["A","B","C"]
case_2 = ["D","E","A"]
result = [i+j for i in case_1 for j in case_2 if not(i==j)]
# Filter: i랑 j과 같다면 List에 추가하지 않음
# [i+j if not(i==j) else i for i in case_1 for j in case_2]


words = 'The quick brown fox jumps over the lazy dog'.split()
# 문장을 빈칸 기준으로 나눠 list로 변환
#print (words)
'''
['The', 'quick', 'brown', 'fox', 'jumps',
'over', 'the', 'lazy', 'dog']
'''
>>> stuff = [[w.upper(), w.lower(), len(w)]
for w in words]
# list의 각 elemente들을 대문자, 소문자

Two dimensional array가 필요

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
case_1 = ["A","B","C"]
case_2 = ["D","E","A"]

result = [[i+j for i in case1] for j in case2]
#뒤에께 먼저 작동하고
'''
for j in case2:
line = []
for i in case1:
line.append(i+j)

result = [['AD','BD','CD'], ['AE','BE','CE'],['AA','BA','CA']]

'''

2-3) Enumerate & Zip

Enumerate

1
2
3
4
5
6
7
8
9
10
11
my_str = 'ABCD'
d = {v:i for i,v in enumerate(my_str)}

mylist = ['a', 'b', 'c', 'd']
l = list(enumerate(mylist))
#[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

{i:j for i,j in enumerate('Artificial intelligence (AI), is intelligence demonstrated by machines,unlike the natural intelligence displayed by humans and animals.'.split())}

#문장을 공백을 기준으로 나누어 단어들의 list로 만들고 list의 index와 값을 unpacking하여 dict로 저장

Zip

두개의 list의 값을 병렬적으로 ==tuple== 타입으로 추출하여 저장

1
2
3
4
5
6
math = (100,80,90)
kor = (90,90,80)
eng = (90, 80, 70)

result = [sum(value)/3 for value in zip(math,kor,eng)]
# [세학생의 평균점수가 저장됨]

같은 위치에 있는 값들!!

2-4) Lambda & Map & Reduce

Lambda

  • 함수 이름없이 쓸수있는 익명함수
  • 수학의 람다 대수에서 유래됨

ex)

1
2
3
4
5
6
7
f = (lambda x,y : x+y)
f(10,50)
#60 값이 return 이됨

up_low = lambda x: x.upper()+ x.lower()
# s = up_low("my happy")
# s = "MY HAPPYmy happy"

파이썬 3부터 권장되지 않음

def를 걍써라

  • 문법이 어려움
  • 함수 작동의 test 가어려움
  • docstring이 없음
  • 다른사람들의 코드 해석이 어려움
  • 이름이 존재하지 않는 함수가 생김

Map

  • sequnce형 data가있을때 함수에 각각 적용을 해주고 그결과를 받는 기능

  • 두개이상의 list에 적용가능, if filter도 사용가능

ex)

1
2
3
4
5
6
7
8
ex = [1,2,3,4]
f = lambda x : x**2
l = list(map(f,ex))
l = [f(value) for value in ex]
# l = [1,4,9,16]
f = lambda x,y : x*y
l = list(map(f,ex,ex))
# l = [1,4,9,16]

Reduce

  • map function과 달리 list에 똑같은 함수를 적용해서 통합
1
2
3
4
5
6
7
8
9
10
11
from functools import reduce

x = reduce(lambda x,y : x+y, [1,2,3,4,5])
'''
1+2 = 3
3+3 = 6
6+4 = 10
10+5 = 15
따라서 x = 15의 값이 나온다

'''

머신러닝에서는 여전히 Lambda, Map, Reduce를 많이 사용함

2-5) Iterable Object

  • Sequnce형 자료형(list,tuple,문자열 등등)에서 데이터를 순서대로 추출하는 object
1
2
for city in ['s','t','n']:
print(city)

위와 같이 data를 순서대로 추출하는

  • 내부적으로는 iter 과 __next___가사용됨
  • iter(), next() 함수로 한개씩 넘어감
1
2
3
4
5
6
7
8
9
10
11
12
cities = ['Seoul',"Busan","Jeju"]
# 이자체가 모두 memory에 올라가게 됨 그런데

memory_iter_object = iter(cities)
# 이렇게 해버리면 memory 다음위치들에 대한 주소값을 가져오게됨
print(next(memory_iter_object))
#Seoul
print(next(memory_iter_object))
#Busan
print(next(memory_iter_object))
#'Jeju'

{: .align-center}

이런식으로 iterable object가 저장이 됨

list는 사실 cities라는게 포인터고 배열안에 주소값이 각각저장되어있어 각 index마다 주소값이 저장되어있음

이걸 iterable 한 object로 해주면

node가 다음객체의 주소값을 가지고있음

Generator(몰랐던거라 매우 중요)

Generator

  • iterable object를 특수한 형태로 사용하는 함수

  • element가 사용되는 시점에 값을 메모리에 반환

    : yeild를 사용하여 한번에 하나의 element만을 반환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import sys
def general_list1(value):
result= []
for i in range(value):
l.append(i)
return result

print(general_list1(50))
#[1,2,3,...,49]
result = general_list1(50)
sys.getsizeof(result)
#520
def general_list2(value):
result = []
for i in range(value):
yeild i

print(general_list2(50))
# <generator object>
for a in general_list2(50):
print(a)
#평소에는 memory에 실제로 값이 안들어가 있고 주소값만을 가지고 있음
#print 호출시 주소값을 활용하여 yeild가 값을 줌
# 따라서 generator를 사용하면 memory 사이즈를 줄일수있음, 대용량 data

Generator Comprehension

1
2
3
4
g = (n*n for n in range(500))
print(type(g))
#<class generator>

2-6) Function Passing Argument

  1. Keyword argument
  2. Default argument
  3. Variable-length arguments

Keyword argument

  • 함수에 입력되는 parameter의 변수명을 사용, arguments를 넘김

이름대로 함수에 parameter가 들어감 (순서가 X)

1
2
3
4
def print_somthing(my_name, your_name):
print("Hello {0}, My name is {1}".format(your_name, my_name))
print_somthing("Sungchul", "TEAMLAB")
print_somthing(your_name="TEAMLAB", my_name="Sungchul")

Default argument

굳이 넣어주지 않아도 default로 값을 설정해줄시 그값으로 생성이됨

1
2
3
4
def print_somthing_2(my_name, your_name="TEAMLAB"):
print("Hello {0}, My name is {1}".format(your_name, my_name))
print_somthing_2("Sungchul", "TEAMLAB")
print_somthing_2("Sungchul")

Variable Length arguments

함수의 parameter가 정해져있지 않았다면 ? -> asterisk(가변인자)를 사용

  • *args를 변수명으로 사용

{: .align-center}

위와 같이 사용가능

*args의 type은 tuple형태로 여러개의 값이 묶임

Keyword variable - length

  • Parameter 이름을 따로 지정하지 않고 입력하는 방법
  • asterisk 2개를 사용하여 함수의 parameter를 표시
  • 입력된 값들은 dict로 사용가능
  • 가변인자는 오직 한개만 기존 가변인자 다음에 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def kwargs_test_1(**kwargs):
print(kwargs)
print(type(kwargs))


kwargs_test_1(first = 3, second = 4, third = 5)
'''
{'first' : 3, 'second' : 4, 'third' = 5}
<class dict>
'''

def kwargs_test_3(a,b,c,*args,**kwargs):
print(a+b+c+sum(args))
print(kwargs)

kwargs_test_3(1,2,3,5,2,1, first = 3,second = 4,third = 5)
'''
13
{'first' : 3, 'second' : 4, 'third' : 5}
'''


2-7) Asterisk

Unpacking a container

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def astersk_test(a, *args):
print(a,args)
print(type(args))

astersk_test(1,*(2,3,4,5))
#이때 tuple 1개의 변수가 들어간다고 생각하지만 *가 들어가서 tuple이 풀리게 됨
# 따라서 astersk_test(1,2,3,4,5)라고 생각함
astersk_test(1,(2,3,4,5))
# 1 ((2, 3, 4, 5),)
# <class 'tuple'>

print(*[1,2,3,4])
#1 2 3 4
print([1,2,3,4])
#[1, 2, 3, 4]

a,b,c = ([1,2],[2,3],[3,4])
print(a,b,c)
data = ([1,2],[2,3],[3,4])
print(data)
print(*data)
'''
[1, 2] [2, 3] [3, 4]
([1, 2], [2, 3], [3, 4])
[1, 2] [2, 3] [3, 4]
'''
# zip을 활용
data = ([1,2],[3,4],[5,6])
for d in zip(*data):
print(d)
#(1, 3, 5)
#(2, 4, 6)

#만약 위에게 없으면
data = ([1,2],[3,4],[5,6])
a,b,c = data
for d in zip(a,b,c):
print(d)

# keyword unpacking
def ast(a,b,c,d):
print(a,b,c,d)
data = {'a' : 1, 'b' :2, 'c' : 4}
ast(10,**data)
#10 1 2 4
  • ==asterisk가 함수의 argument로 들어갔을때 unpacking이 일어난다==
  • asterisk를 2개 사용시 keyword unpacking이라고 바꿔준다

새롭게 배운것

  • ==default dict==
  • ==named tuple==
  • ==reduce==
  • ==generator==
  • ==Variable Length arguments==
  • ==Keyword variable - length==
  • ==Asterisk==
Author

jo-member

Posted on

2021-01-20

Updated on

2021-07-12

Licensed under

Comments