Hyun Seup Jo

1주차 - Pythonic Code 본문

Machine Learning

1주차 - Pythonic Code

soup1997 2021. 1. 19. 03:28

[List Comprehension]

기존 List를 사용하여 간단히 다른 List를 만드는 기법

1) 파이썬에서 가장 많이 사용되는 기법 중 하나

2) for + append 보다 속도가 빠른 특징을 가지고 있음

Ex1)

1부터 9까지의 값중 2로 나누었을 때 나머지가 0인것만 리스트 안에 넣기

result = []
for i in range(10):
    if i % 2 == 0:
    	result.append(i)
print(result)
[0, 2, 4, 6, 8]

 


위와 비교한 pythonic code 예시(동일 결과)

result = [i for i in range(10) if i % 2 == 0] # i값이 순차적으로 대입됨 + filter 기법
print(result)
[0, 2, 4, 6, 8]

 

Ex2)

word_1 = "Hello"
word_2 = 'World'
result = []
for i in word_1:
    for j in word_2:
        result.append(i + j)
print(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']

위의 예시를 pythonic code로 나타낸 경우(동일 결과)

word_1 = 'Hello'
word_2 = 'World'
result = [i + j for i in word_1 for j in word_2]
print(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']

 

Ex3)

case1 = ['A', 'B', 'C']
case2 = ['D', 'E', 'A']
result = [i + j for i in case1 for j in case2 if i != j]
print(result) # 1차원 리스트 형태(앞의 for문이 고정)

result = [[b + a for a in case1] for b in case2]
print(result) # 2차원 리스트 형태(뒤의 for문이 고정)
['AD', 'AE', 'BD', 'BE', 'BA', 'CD', 'CE', 'CA']
[['DA', 'DB', 'DC'], ['EA', 'EB', 'EC'], ['AA', 'AB', 'AC']]

 

Ex4)

words = 'The quick brwon fox jumps over the lazy dog'.split() # 문장을 빈칸 기준으로 나눠 list로 반환
print(words) # 리스트 반환결과 출력
print("")
stuff = [[w.upper(), w.lower(), len(w)] for w in words] # words리스트에 있는 요소들을 각각 [대문자, 소문자, 단어길이]로 구성된 하나의 리스트로 묶음
for i in stuff:
    print(i)
['The', 'quick', 'brwon', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']

['THE', 'the', 3]
['QUICK', 'quick', 5]
['BRWON', 'brwon', 5]
['FOX', 'fox', 3]
['JUMPS', 'jumps', 5]
['OVER', 'over', 4]
['THE', 'the', 3]
['LAZY', 'lazy', 4]
['DOG', 'dog', 3]

[Enumerate & Zip]

Enumerate - 리스트의 요소를 추출할 때 번호를 붙여서 추출한다

Ex1)

for (i, v) in enumerate(['tic', 'tac', 'toe']):
    print(i, v)
0 tic
1 tac
2 toe

enumerate([리스트 요소])를 통해 각각 인덱스와 요소값을 하나의 튜플로 묶어 반환한다. 만약 print(enumerate(['tic', 'tac', 'toe']))와 같이 적을 경우 enumerate객체가 있는 주소를 출력하게 된다. 

 

Ex2)

mylist = ['a', 'b', 'c', 'd']
result = list(enumerate(mylist)) # 만약 어떤 변수에 enumerate반환 값을 대입하고 싶다면 이와 같이 가능하다.
print(result)

result = {i: j for (i, j) in enumerate('KPU is an academic institute located in South Korea.'.split())}
print(result) # dict로 처리하기 위해 중괄호 처리
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
{0: 'KPU', 1: 'is', 2: 'an', 3: 'academic', 4: 'institute', 5: 'located', 6: 'in', 7: 'South', 8: 'Korea.'}

Zip - 두개의 list의 값을 병렬적으로 추출함(같은 인덱스끼리 묶어서 반환)

마찬가지로 print(zip(~))과 같이 코드를 작성할 경우 Zip객체가 위치해 있는 주소를 반환하므로 형변환이 필요하다.

Ex1)

alist = ['a1', 'a2', 'a3']
blist = ['b1', 'b2', 'b3']
for (a, b) in zip(alist, blist): # 병렬적으로 값을 추출
    print(a, b)
a1 b1
a2 b2
a3 b3

 

Ex2)

a, b, c = zip((1, 2, 3), (10, 20, 30), (100, 200, 300))
print(a, b, c)
result = [sum(x) for x in zip((1, 2, 3), (10, 20, 30), (100, 200, 300))]
print(result) # 벡터의 연산과 동일
(1, 10, 100) (2, 20, 200) (3, 30, 300)
[111, 222, 333]

 

Ex3) Enumerate와 Zip을 동시에 사용한 예시

alist = ['a1', 'a2', 'a3']
blist = ['b1', 'b2', 'b3']
for i, (a, b) in enumerate(zip(alist, blist)):
    print(i, a, b) # 같은 인덱스에 위치한 요소끼리 묶은 다음 인덱스랑 같이 추출
0 a1 b1
1 a2 b2
2 a3 b3

[Lambda & MapReduce]

Lambda - 함수를 선언하지 않고도 한줄에 작성할 수 있는 임시적인 함수

파이썬에서 가장 일반적인 함수의 정의는 다음과 같다.

def f(x, y):
    return x + y
print(f(1, 4)) # 함수의 호출
5

이와 동일한 기능을 하는 lambda함수의 사용방법은 다음과 같다.

f = lambda x, y: x + y # x, y는 함수의 호출에서 인자를 받아 x + y를 return 한다.
print(f(1, 4))
5

Map - sequence 자료형의 각 요소에 동일한 함수를 적용함.

Ex1)

ex = [1, 2, 3, 4, 5]
f = lambda x: x ** 2
print(list(map(f, ex))) # list를 안쓰면 map객체의 주소를 돌려줌
[1, 4, 9, 16, 25]

리스트로 선언된 ex에서 f함수 호출에 의해 제곱 연산을 한다. 다음 요소도 f함수가 적용이 되어 제곱값이 반환된다. 


result = [value ** 2 for value in ex] # list를 쓰지 않은경우
print(result)
[1, 4, 9, 16, 25]

Ex2)

result = map(int, input('값을 입력하세요:').split())
print(list(result))
값을 입력하세요:1 2 3 4 5
[1, 2, 3, 4, 5]

위의 예시와 더불어 파이썬에서 여러 변수를 동시에 입력받고 리스트로 출력하는 방법을 살펴보자. split에 의해 공백으로 문자 구분을 하여 여러개의 변수를 입력 받고 map에 의해 적용된 함수는 int이므로 문자가 정수형으로 형변환 되어 list로 출력하는 방식이다.


Map Reduce - map과 유사하며 iterable한 자료형에 똑같은 함수를 적용한다.

reduce 함수는 매개변수로 (함수, 반복자료형, 초깃값)을 가지며 초깃값은 넣어주지 않아도 된다.

Ex1) 팩토리얼을 계산하는 함수를 작성해 보자.

def factorial(num):
    if num == 0:
        return 1
    else:
        return num * factorial(num - 1)

위와 같은 팩토리얼 함수를 reduce와 lamda를 통해 다음과 같이 정의 가능하다.

def factorial(n):
    return reduce(lambda x, y: x * y, range(1, n + 1))
print(factorial(5))
120

[Asterlisk]

Asterlisk는 흔히 알고 있는 *을 의미함, 단순 곱셈, 제곱연산, 가변 인자등 다양하게 활용된다.

Ex1)

def asterlisk_test(a, *args): # *은 가변인자 의미
    print(a, args)
    print(type(args))
asterlisk_test(1, 2, 3, 4, 5, 6) 
asterlisk_test(1, (2, 3, 4, 5, 6))
1 (2, 3, 4, 5, 6)
<class 'tuple'>

1 ((2, 3, 4, 5, 6), )
<class 'tuple'>

앞의 첫인자인 a는 1이 들어가며 *args에는 튜플의 나머지 요소들이 대입된다. *은 여기서 1을 제외한 나머지 요소들을 묶는 역할(packing)을 하며 출력결과를 보면 알 수 있듯이 1개의 튜플로 출력된다. 두번째의 asterlisk_test(1, (2, 3, 4, 5, 6))의 함수 호출 경우 *args에는 (2, 3, 4, 5, 6)으로 묶인 하나의 튜플이 인자로 대입된다. *에 의해 튜플로 묶인 하나의 값이 한번 더 묶이게 되면서 ((2, 3, 4, 5, 6), )과 같이 출력된다.

Ex2)

def asterlisk_test2(a, **kargs):  # **는 dict type으로 들어감
    print(a, kargs)
    print(type(kargs))
asterlisk_test2(1, b = 2, c = 3, d = 4, e = 5, f = 6)
1 {'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}
<class 'dict'>

**을 사용하게 되면 dict type으로 형변환이 되어 asterlisk_test2(1, b = 2, c = 3, d = 4, e = 5, f = 6)과 같은 인자들이 asterlisk_test2(1, b = 2, c = 3, d = 4, e = 5, f = 6)처럼 출력된다.

 

Ex3)

def asterlisk_test4(a, args):
    print(a, *args) # (2, 3, 4, 5, 6)의 tuple하나의 값을 unpacking
    print(type(args))
asterlisk_test4(1, (2, 3, 4, 5, 6))
1 2 3 4 5 6
<class 'tuple'>

함수의 매개변수에 *이 들어갔을때와는 달리 print(a, *args)의 경우 (2, 3, 4, 5, 6)으로 묶인 하나의 튜플을 unpakcing하여 출력한다. 

 

Ex4) 

a, b, c = ([1, 2], [3, 4], [5, 6])
print(a, b, c)
data = ([1, 2], [3, 4], [5, 6])
print(*data)
[1, 2] [3, 4] [5, 6]
[1, 2] [3, 4] [5, 6]

*data의 경우도 마찬가지로 튜플로 묶인 하나의 값을 unpacking하여 출력하게 된다.

 

Ex5)

def asterlisk_test5(a, b, c, d):
    print(a, b, c, d)
data = {'b': 1, 'c': 2, 'd': 3}
asterlisk_test5(10, **data)
10 1 2 3

**을 매개변수에 사용하게 될 경우 dict type으로 변하게 된다. 마찬가지로 매개변수가 아닌 다른 위치에서 **를 사용할 경우 dict_type을 unpakcing 하게 된다.

 

Ex6)

for data in zip(*([1, 2], [3, 4], [5, 6])): # 먼저 소괄호를 unpacking 그다음, zip을 통하여 같은인덱스끼리 튜플로 묶음
    print(data)
    print(sum(data))
(1, 3, 5)
9
(2, 4, 6)
12

 

Ex7)

def asterlisk_test(a, b, c, d, e = 0):
    print(a, b, c, d, e)
data = {'d': 1, 'c': 2, 'b': 3, 'e': 56}
asterlisk_test(10, **data)
10 3 2 1 56

**data를 통하여 dict를 unpacking하고 함수 호출결과 각각의 key에 해당 value가 대입되어 출력되는 것을 확인할 수 있다.

 

출처 : www.boostcourse.org/ai222/joinLectures/27854 (머신러닝을 위한 파이썬)

'Machine Learning' 카테고리의 다른 글

3주차 - Pandas(1)  (0) 2021.02.04
3주차 - Numpy Assignment(문제 풀이)  (0) 2021.02.03
2주차 - Numerical Python (numpy)  (0) 2021.01.28
1주차 - Basic Linear Algebra (문제 풀이)  (0) 2021.01.23
1주차 - Linear Algebra  (0) 2021.01.21