Python/Python

Python : 표현식(Comprehension)

scarlet0star 2023. 3. 24. 11:08

사실은 이 의미가 아닐지?

python에서 한줄로 자료구조를 생성할때 사용하는 comprehension 기능을 정리해볼까 한다.  comprehension을 사전에서 검색해보면 이해력이라는 단어가 나오는데 사실은 함축, 내포라는 의미로 사용한 게 아닐까? 만약 그렇다면 왜 comprehension이라는 단어를 썼는지 이해는 간다. 이해력보다는 말이다.

컴프레헨션, 선언과 동시에 자료구조를 채워버리는 방법이다. 그 경제력은 코드만으로도 알아볼 수 있다.

A = []

for i in range(10):
    A.append(i)

B = [i for i in range(10)]

A 와 B는 같은 리스트지만 A를 생성하는데에는 약 3줄이, B를 생성하는데에는 1줄이 필요했다. 여기서 조건이 여러개 필요하다거나 하면 A는 더 늘어나야만 할것이다. 이것만으로도 python을 쓰면서 컴프레헨션을 쓰는 이유를 알 수 있다.


 

[ <저장될 방법> for <변수명> in <순회구조> ] 형식으로 사용한다.

C = [i**2 for i in range(10)]

#[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

D = {i: i for i in range(10)}
E = {i for i in range(10)}
F = tuple(i for i in range(10))

# {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9} 
# {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
# (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

컴프레헨션을 사용하는 방법은 위와 같다. 리스트는 대괄호를 딕셔너리는 중괄호를 사용하고 key:value 형태로 사용하거나 아니면 zip을 이용하여도 된다. tuple은 괄호로 지정할 수는 없고 위와 같이 써야한다. 소괄호만 사용하는 경우는 제너레이터 컴프레헨션인데, 이는 나중에 추가적으로 설명하겠다.

B = [i for i in range(10) if i % 2 == 0]

print(B) # [0, 2, 4, 6, 8]

B = [i for i in range(10) if i % 2 == 0 if i % 3 == 0]

print(B) # [0, 6]

B = [i for i in range(10) if i % 2 == 0 or i % 3 == 0]

print(B) # [0, 2, 3, 4, 6, 8, 9]

이런 형식으로 조건문을 안에 기입하여 순환하면서 필터링하여 채울 수도 있다. 조건 여러개가 AND 구성이면 and를 쓰지 않고 또 다른 if를 쓰고 OR 조건이면 조건문 안에 or를 쓰면 된다.

A = [[j for j in range(5)] for _ in range(3)]

print(A) # [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]

AA = ["a", "b"]
A = [[j for j in range(5)] for _ in AA]
print(A) # [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]

컴프레헨션 안에서 또 다시 컴프레헨션을 사용해도 된다. 위의 경우에서는 0~4를 담은 리스트를 딱히 지칭할 필요가 없어서 _로 썼다. 쓰다보니 궁금해서 순회구조가 range()가 아닐 경우에(보통 그렇게 쓸 일은 없겠지만) 어떻게 될지 살펴보았는데 위 예시처럼 순회구조의 길이만큼 반복되는 것을 확인할 수 있었다.

A = [i for i in range(3)]
B = [i for i in range(3,6)]

C = [(x,y) for x in A for y in B]

print(C) # [(0, 3), (0, 4), (0, 5), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5)]

C = [(x, y) for x in A for y in B if x % 2 == 0 if y % 2 == 1]
print(C) # [(0, 3), (0, 5), (2, 3), (2, 5)]

여러개의 순회구조를 통한 컴프레헨션도 가능하다. 위에서 예시로든 C를 보면 for 루프처럼 뒤에 있는 순회 구조를 먼저 돌고 그 다음 순회 구조를 도는 것을 확인할 수 있다.당연히 조건문도 각각 써줄 수 있다.

이제 컴프레헨션을 이용해 한번에 자료 구조를 생성할 수 있게 되었다!