본문 바로가기
DEVLOG/Python

진작 알았더라면 좋았을 파이썬(Python) 기능 5가지

2020. 1. 3.
반응형

lambda, map, filter를 넘어서...

파이썬은 10년동안 떠오르는 프로그래밍 언어로서 매우 강력한 언어임이 증명되었습니다. 저는 파이썬을 이용해 아주 많은 어플리케이션을 개발해왔습니다. 파이썬에는 너무나 많은 기능이 있고, 초보자들이 처음에는 모든 것을 파악하기 어렵습니다.

 

만약 C나 MATLAB같은 다른 언어를 사용했던 프로그래머일지라도, 더 높은 수준의 추상화를 가진 파이썬은 분명히 다른 경험일 것입니다. 파이썬을 개발하면서 좀 더 일찍 알았더라면 좋았을, 그리고 가장 중요한 5가지에 대해 소개해보려고 합니다.

 

1. List comprehensions - compact codes

많은 사람들은 모든 사람들이 배워야 할 파이썬 기능으로서 lambda, map, filter를 언급할 것입니다. 저 또한 이들이 꼭 알아야 할 기능이라고 생각하지만, flexibility가 부족하기 때문에 특별히 유용하지 않습니다.

 

Lambda는 1회용으로 함수를 구성하는 방법입니다. 함수를 여러번 호출하면 성능이 저하됩니다. 반면에 map은 목록의 모든 요소에 함수를 적용하는 반면, filter는 사용자 정의 조건을 충족하는 집합의 elements 집합을 가져옵니다.

 

add_func = lambda z: z ** 2
is_odd = lambda z: z%2 == 1
multiply = lambda x,y: x*y

aList = list(range(10))
print(aList)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

 

List comprehension은 유연한 표현과 조건으로 다른 리스트로부터 리스트를 만드는 간결한 방법입니다. 대괄호로 구성되며, 특정 조건을 만족하는 경우에만 리스트의 모든 요소에 적용되는 함수로 구성됩니다. 또한 중첩된 리스트를 처리하기 위해 중첩될 수 있으며, map과 filter를 사용하는 것보다 훨씬 유연합니다.

# Syntax of list comprehension
[ expression(x) for x in aList if optional_condition(x) ]
print(list(map(add_func, aList)))
print([x ** 2 for x in aList])
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

print(list(filter(is_odd, aList)))
print([x for x in aList if x%2 == 1])
# [1, 3, 5, 7, 9]
# [1, 3, 5, 7, 9]

 

2. List manipulation - circular lists

파이썬은 aList[-1] == aList[len(aList)-1]에서 음수 인덱스를 허용합니다.

따라서 aList[-2] 등을 불러 리스트의 두 번째 마지막 요소를 가져올 수 있습니다.

 

또한 시작 요소는 포함되지만 마지막 요소는 포함되지 않는 aList[start:end:step] 구문을 사용하여 리스트를 자를 수 있습니다. 따라서 aList[2:5]를 호출하면 [2, 3, 4]가 됩니다. 또한 aList[::-1]을 호출하면 리스트를 뒤집을 수 있는데, 저는 이 테크닉을 유용하게 쓰고 있습니다.

 

리스트는 별도의 요소로 풀거나, 별표를 사용하여 요소와 하위 리스트를 혼합할 수도 있습니다.

a, b, c, d = aList[0:4]
print(f'a = {a}, b = {b}, c = {c}, d = {d}')
# a = 0, b = 1, c = 2, d = 3

a, *b, c, d = aList
print(f'a = {a}, b = {b}, c = {c}, d = {d}')
# a = 0, b = [1, 2, 3, 4, 5, 6, 7], c = 8, d = 9

 

3. Zipping and enumerate - for-loops

zip함수는 여러 리스트에서 요소를 집계하는 iterator를 생성합니다. 

numList = [0, 1, 2]
engList = ['zero', 'one', 'two']
espList = ['cero', 'uno', 'dos']
print(list(zip(numList, engList, espList)))
# [(0, 'zero', 'cero'), (1, 'one', 'uno'), (2, 'two', 'dos')]

for num, eng, esp in zip(numList, engList, espList):
    print(f'{num} is {eng} in English and {esp} in Spanish.')
# 0 is zero in English and cero in Spanish.
# 1 is one in English and uno in Spanish.
# 2 is two in English and dos in Spanish.
Eng = list(zip(engList, espList, numList))
Eng.sort() # sort by engList
a, b, c = zip(*Eng)

print(a)
print(b)
print(c)
# ('one', 'two', 'zero')
# ('uno', 'dos', 'cero')
# (1, 2, 0)

 

Enumerate는 꽤 자주 유용하게 쓰입니다. for-loop에서 흔히 사용되는 자동 카운터로서, counter=0과 counter+=1에 의해 for-loop에서 더 이상 카운터 변수를 생성하고 초기화할 필요가 없습니다. Enumerate와 zip은 for-loop을 구성할 때 가장 강력한 두 가지 도구입니다.

upperCase = ['A', 'B', 'C', 'D', 'E', 'F']
lowerCase = ['a', 'b', 'c', 'd', 'e', 'f']
for i, (upper, lower) in enumerate(zip(upperCase, lowerCase), 1):
    print(f'{i}: {upper} and {lower}.')
# 1: A and a.
# 2: B and b.
# 3: C and c.
# 4: D and d.
# 5: E and e.
# 6: F and f.

 

4. Generator - memory efficiency

Generator는 큰 결과 집합을 계산할 때 사용되지만, 모든 결과에 필요한 메모리를 동시에 할당하지 않으려고 할 때 사용됩니다. 즉, 즉시 값을 생성하고 이전의 값을 메모리에 저장하지 않기 때문에 우리는 그 값을 한번만 반복할 수 있습니다. 큰 파일을 읽거나 키워드를 사용하여 무한 시퀀스를 생성할 때 자주 사용됩니다.

def gen(n):    # an infinite sequence generator that generates integers >= n
    while True:
        yield n
        n += 1
        
G = gen(3)     # starts at 3
print(next(G)) # 3
print(next(G)) # 4
print(next(G)) # 5
print(next(G)) # 6

 

5. Virtual environment - isolation

이 글에서 단 한 가지만 기억할 수 있다면 가상환경을 사용하는 것입니다.

 

파이썬 어플리케이션은 종종 복잡한 의존성을 가진 다양한 개발자들의 많은 다른 패키지를 사용합니다. 다른 어플리케이션은 다른 라이브러리 버전을 사용하여 결과를 복제할 수 없는 특정 라이브러리 설정을 사용하여 개발됩니다. 모든 어플리케이션의 요구사항을 만족하는 설치는 단 한 건도 존재하지 않습니다.

conda create -n venv pip python=3.7  # select python version
source activate venv
...
source deactivate

 

따라서 pip 또는 conda를 사용하여 수행할 수 있는 각 어플리케이션에 대해 별도의 자체적인 가상환경을 만드는 것이 필수적입니다.

 

 

반응형

댓글