# Comprehension

 


 

1. list comprehension

 

파이썬에서 for문은 사용할 수 있는 범위가 굉장히 넓습니다. 예를 들어 리스트를 하나 만들고 그 안에 값을 동적으로 추가해야 하는 상황이라면 아래와 같은 방법을 이용할 수 있겠죠.

myList = []

for i in range(10):
	myList.append(i) # [0,1,2,3,4,5,6,7,8,9]

 

만약에 리스트에 값을 삽입하는 규칙이 있다면, 리스트를 선언하면서 값을 삽입 할 수 있으면 편하지 않을까요? 파이썬에서는 이를 Comprehension이라고 하고 리스트나 딕셔너리에 적용하는 것이 가능합니다.

 

myList = [i for i in range(10)] # [0,1,2,3,4,5,6,7,8,9]

 

위의 코드가 바로 list comprehension 입니다. 리스트를 선언함과 동시에 리스트 안에 for 문을 넣어 요소를 저장하는 방법인데요 for 문의 i가 늘어남과 동시에 i의 값이 저장되는 모습입니다. 즉 가장 앞에 명시한 변수에 저장된 값이 반복문이 실행되면서 리스트의 요소로써 저장되는 것입니다.

 

만약 list comprehension에 for문만 사용이 가능하다고 한다면 의미가 없는 구문일 수 있습니다. 역시 파이썬 제작자는 이를 간파하고 if else등의 제어문도 사용할 수 있게 만들었습니다.

 

#if
myList = [i for i in range(10) if i%2==0] # [0,2,4,6,8]

#if else
myList = [i if i%2==0 else i-1 for i in range(10)] # [0,0,2,2,4,4,6,6,8,]

#nested loop
myList = [j for i in range(3) for j in range(3)] # [0,1,2,0,1,2,0,1,2]

위 의 코드를 보면 if 와 if - else를 쓸 때의 문법의 차이가 있다는 것을 느끼셨을 텐데요, if 는 for문 뒤에오는 반면 if-else는 for 문 전에 옵니다. 그리고 if문은 조건문에 부합하는 요소만 저장하는 반면에 if-else는 조건문에 부합하지 않는 요소도 값을 변형시켜서 저장할 수 있습니다.(i-1)

 

list comprehension은 편리한 기능이지만, 이를 무분별하게 사용하는 것은 코드의 가독성을 해칩니다. 따라서 조건문이 다중이거나 nested된 반복문이라면 list comprehension을 지양하는 것이 좋습니다.

 


 

2. dictionary comprehension

 

사실 dictionary는 list 만큼 comprehension이 유용하지 않습니다. 하지만 길이가 같은 리스트 2개를 각각 Key Value로 삼아 딕셔너리로 형변환 하고자 한다면 유용하게 사용할 수 있습니다.

 

아래의 코드를 보시면 for문을 이용하여 길이가 같은 리스트 2개를 딕셔너리로 만드는 방법이 기재 되어있습니다. 기존의 코드는 리스트의 크기만큼 for문을 실행시켜서 딕셔너리에 각각의 Key, Value로 저장하는 방법인데요, 저는 개인적으로 Dictionary comprehension이 코드의 길이도 짧고 특정상황에서는 훨씬 가독성이 좋다고 생각합니다.

myList_1 = [1,2,3]
myList_2 = ['a','b','c']

# original code
newDict = dict()
for i in range(len(myList_1)):
    newdict[myList_1[i]] = myList_2[i]

# dictionary comprehension
newDict = {myList_1[i]: myList_2[i] for i in range(len(myList_1))}

 

Dictionary comprehension은 dictionary의 Key-Value를 반전시키는데도 사용할 수 있습니다. dictionary class의 메소드로 제공되고 있는 items()는 dictionary의 모든 key,value쌍을 tuple로 상속된 객체를 리턴합니다. 해당 객체는 iteration 클래스이기 때문에 for문의 iterable 객체로 사용할 수 있습니다. 그렇기 때문에 다음과 같은 방식을 이용하면 dictionary  Key-Value를 반전 시킬 수 있습니다.

 

# original code
myDict = {1: 'a', 2: 'b', 3: 'c'}
newDict = dict()
for key,value in myDict.items():
    newDict[value] = key

# dictionary comprehension
myDict = {1: 'a', 2: 'b', 3: 'c'}
newDict = {value : key for key,value in myDict.items()}

 

 


 

3. zip함수를 이용한 자료형 변환

 

파이썬에서 기본으로 제공하고 있는 zip함수는 리스트를 딕셔너리로 변경해주거나 딕셔너리의 Key-Value를 반전시키는데 가장 효율적인 함수입니다. 

# List to dictionary
myList_1 = [1,2,3]
myList_2 = ['a','b','c']
newDict = dict(zip(myList_1,myList_2))

# Key-Value reverse
myDict = {1: 'a', 2: 'b', 3: 'c'}
reverse_dictionary = dict(zip(myDict.values(),myDict.keys()))

위 코드는 zip함수를 이용하여 list 2개를 dictionary로 변환시키는 코드입니다. Dictionary comprehension이나 일반적인 for문으로 변환 시키는것보다 코드의 길이도 짧고 가독성도 훌륭합니다. 

또한 마지막 라인을 보시면 zip함수를 이용하여 dictionary를 반전시켰습니다. dictionary class의 메소드인 values()와 keys()를 이용하여 모든 value와 key를 추출하고 zip함수의 첫 번째, 두 번째 인자로 넣습니다.

여기까지만 하면 zip 클래스의 인스턴스가 되게 됩니다. 이 객체는 Iterable하지만 dictionary라고 할 수 없죠, 그래서 전체 구문을 dict로 감싸 형변환을 마무리합니다.

 

 

'Dev > python' 카테고리의 다른 글

[python] 클래스(class)와 인스턴스  (1) 2019.04.07
[python] 함수  (0) 2019.04.04
[python] 제어문(if, for, while) - 3  (0) 2019.03.23
[python] 시퀀스 자료형과 이터러블  (1) 2019.03.23
[python] 제어문(if, for, while) - 2  (0) 2019.03.23

+ Recent posts