본문 바로가기

기타

[#1] Python을 Python 답게 사용하는 방법

map과 filter 대신 list comprehension을 쓰자 


보통 리스트에서 원소별 계산을 하거나 필터링 하고자 할 때 다음과 같이 쓴다. 


1
2
3
4
5
6
7
= [1,2,3,4,5,6,7,8,9,10]
 
#여기서 각 원소별 제곱을 하기 위해 보통 map을 사용한다
squares = map(lambda x: x ** 2, a)
 
#혹은 필터링을 위해서는 filter()를 사용한다. 
result = filter(lambda x: x % 2 == 0, a)
cs


위와 같은 방법을 쓸 수 있지만 람다를 사용하게 될 경우 한눈에 파악하기 힘들다.

이를 위해 list comprehension을 사용할 수 있다. 


1
2
3
4
5
6
7
= [1,2,3,4,5,6,7,8,9,10]
 
#다음과 같이 list comprehesion을 사용할 경우 한눈에 들어온다.
squares = [x*for x in a]
 
#필터링 계산식도 한 눈에 확인하기 쉽다.
result = [x for x in if x % 2 == 0]
cs



Comprehension이 클 때는 제네레이터 표현식을 고려하자. 

만약 큰 Comprehension을 처리하고자 한다면 Generator를 사용하는 편이 낫다. 

예를들어 파일을 읽어 각 줄에 있는 문자의 개수를 반환하고자 할 때 Comprehension을 사용하게 될 경우

메모리의 낭비가 심하게 된다. 

읽어들이는 데이터에 대해 모두 메모리에 들고 있기 때문이다. 


generator를 사용하는 방법은 간단하다.

list comprehension이 '['를 사용했다면 generator의 경우'('을 사용하면 된다. 


1
2
3
4
5
6
= [12345678910]
it = (x for x in a)
print(it)
 
# generator는 iterator를 반환하며 이를 출력하면 다음과 같이 확인할 수 있다.
#<generator object <genexpr> at 0x000001B6EA74A8E0>
cs


range 보다는 enumerate를 사용하자


보통 리스트의 값들을 순회 할 경우 다음 처럼 구현하게 된다. 

1
2
3
4
flavor_list = ['vanila''chocolate''pecan''strawberry']
 
for i in range(len(flavor_list)):
    print(flavor_list[i])
cs


위와 같이 사용할 경우 리스트의 길이를 알아야 하고 인덱스로 접근해야 하기 때문에 읽기 불편할 수도 있다.


enumerate는 lazy generator로 iterator를 감싼다. 

이 generator는 iterator에서 각 원소의 index, 원소값을 쌍으로 반환하게 된다. 


1
2
3
4
5
6
7
8
9
10
11
flavor_list = ['vanila''chocolate''pecan''strawberry']
 
for idx, flavor in enumerate(flavor_list):
    print("index={0}, flavor={1}".format(idx, flavor))
 
"""
index=0, flavor=vanila
index=1, flavor=chocolate
index=2, flavor=pecan
index=3, flavor=strawberry
"""
cs

위와 같이 사용하게 되면 별도의 길이를 계산하지 않고도 list를 순회할 수 있으며 index와 원소를 각각 접근 할 수 있다. 

'기타' 카테고리의 다른 글

Python Distutils  (0) 2017.02.24
#3 쿠쿠 설정 파일에 대한 정보2  (0) 2017.02.07
#2 Cuckoo의 Configurations  (0) 2017.01.19
[#1] Cuckoo란 무엇인가?  (0) 2017.01.19
HDFS  (0) 2017.01.09