본문 바로가기

Algorithms and Languages/Python

[Python] 튜플을 큐(덱)에 넣을 때 할 수 있는 실수 - 원소가 한 개인 튜플.

https://www.acmicpc.net/problem/7562

 

해당 문제를 풀던 중, 다음과 같이 코드를 짜고 있었다. 일반적으로 덱에 튜플을 정의할 때 많이 쓰는 코드 뭉치이다.

queue = deque([(sx, sy, 0)])

근데, 의문점이 생겼다. 

 

저거 튜플 하나가 메모리에 잡히고, 그 튜플을 감싸는 리스트가 메모리에 잡히게 된 다음에, 그걸 deque에 일종의 append를 하는 과정이 압축되어 있는 건데,

 

리스트보단 튜플이 아주 미미하지만 오버헤드 때문에 메모리 사용량이 더 크므로(더블링을 위한 정보 등을 저장해야 하니까),

그냥 튜플로 튜플을 감싸서 deque에 넣으면 안 될까?

 

즉, 아래처럼 말이다.

queue = deque(((sx, sy, 0)))

근데... 이렇게 하면, `sx`, `sy`, `0` 이 3개의 원소가 각각 deque에 append되게 된다.

 

즉, 아래처럼 코드를 짜게 되면 오류가 난다. 

단 하나의 원소 `sx`만이 pop돼서 언패킹이 불가하기 때문이다.

queue = deque(((sx, sy, 0)))
x, y, t = popleft() # 오류 발생!

그 이유는 생각보다 간단했는데...

 

우리가 잊고 있던 사실, '원소가 하나인 튜플을 정의할 때는, 컴마를 적지 않으면 괄호가 생략된다(또는 튜플로 평가하지 않고, 그 내부에 있는 원소 자체로 평가한다)'를 떠올려보면 바로 이해된다...

 

즉, 아래와 같이 코드를 짜야 했다.

queue = deque(((sx, sy, 0),)) # 컴마가 추가됨

결론은, 어차피 메모리 차이도 거의 안나는데 그냥 리스트 쓰자는 것이다.

코딩할 때 미미한 효율성보단, 가독성을 챙기는 게 더 나은 상황도 있는데, 이런 게 그런 상황이라 생각한다.

 

정리하면 아래와 같다.

from collections import deque

# 일반적인 사용법
queue = deque([(1, 2, 3)])
print(queue)
x, y, z = queue.popleft()
print(x, y, z)

# 튜플을 굳이 써야겠다면
queue1 = deque(((1, 2, 3),))
print(queue1)
x, y, z = queue1.popleft()
print(x, y, z)

# 오류가 나는 사용법
queue2 = deque(((1, 2, 3)))
print(queue2)
x, y, z = queue2.popleft()
print(x, y, z)