파이썬을 사용하다 보면 my_list.pop()을 써서 리스트의 마지막 항목을 제거하고, my_dict.pop('key')를 써서 딕셔너리의 항목을 제거하는 등 다양한 객체에서 .pop()을 사용하는 자신을 발견하게 됩니다.
마치 pop()이 어떤 객체에든 붙여 쓸 수 있는 만능 인스턴스 메서드처럼 느껴지기도 합니다. 이 pop() 메서드의 정체는 무엇일까요?
1. 'pop()'은 하나가 아닙니다
결론부터 말하면, list의 pop()과 dict의 pop()은 이름만 같을 뿐, 실제로는 완전히 다른 메서드입니다.
-
list클래스는 리스트에 맞는pop()메서드를 자체적으로 정의하고 있습니다. -
dict클래스 역시 딕셔너리에 맞는pop()메서드를 자체적으로 정의합니다. -
set클래스도 마찬가지입니다.
이처럼 서로 다른 객체가 같은 이름의 메서드를 가지는 것은 파이썬의 객체 지향 특성 중 하나인 다형성(Polymorphism) 과 관련이 깊습니다. 'pop'이라는 이름은 "데이터 구조에서 항목을 하나 꺼내고(pop) 반환한다"는 관습적인 의미를 공유할 뿐입니다.
2. 클래스별 pop()의 서로 다른 작동 방식
이름이 같다고 해서 작동 방식까지 같은 것은 아닙니다. 각 클래스는 자신의 자료 구조에 맞게 pop()을 구현했습니다.
1. list.pop([index])
-
동작: 리스트에서 특정 인덱스(index)의 항목을 제거하고 그 항목을 반환합니다.
-
특징: 인덱스를 지정하지 않으면, 기본값으로
-1이 적용되어 가장 마지막 항목을 제거합니다. 스택(Stack) 자료구조의 'pop' 연산과 동일합니다. -
예제:
my_list = ['a', 'b', 'c']
# 인덱스 미지정 (마지막 항목 'c' 제거)
last_item = my_list.pop()
print(f"반환된 값: {last_item}, 남은 리스트: {my_list}")
# 출력: 반환된 값: c, 남은 리스트: ['a', 'b']
# 인덱스 0 지정 ('a' 제거)
first_item = my_list.pop(0)
print(f"반환된 값: {first_item}, 남은 리스트: {my_list}")
# 출력: 반환된 값: a, 남은 리스트: ['b']
2. dict.pop(key[, default])
-
동작: 딕셔너리에서 특정 키(key)에 해당하는 항목(key-value 쌍)을 제거하고 그 값을 반환합니다.
-
특징:
list.pop()과 달리 인덱스가 아닌 키(key)를 반드시 전달해야 합니다. 만약 키가 없는데default값이 주어지면 그 값을 반환하고,default값도 없으면KeyError가 발생합니다. -
예제:
my_dict = {'apple': 1, 'banana': 2}
# 'apple' 키 제거
item = my_dict.pop('apple')
print(f"반환된 값: {item}, 남은 딕셔너리: {my_dict}")
# 출력: 반환된 값: 1, 남은 딕셔너리: {'banana': 2}
# 없는 키('grape')를 시도 (default 값 99 반환)
default_item = my_dict.pop('grape', 99)
print(f"반환된 값: {default_item}, 남은 딕셔너리: {my_dict}")
# 출력: 반환된 값: 99, 남은 딕셔너리: {'banana': 2}
3. set.pop()
-
동작: 세트(set)에서 임의의 항목을 제거하고 그 항목을 반환합니다.
-
특징: 세트는 순서가 없는 자료구조이므로, 어떤 항목이 제거될지 예측할 수 없습니다.
pop()에 아무 인자도 전달하지 않습니다. -
예제:
my_set = {10, 20, 30}
# 임의의 항목 제거 (어떤 값이 나올지 모름)
item = my_set.pop()
print(f"반환된 값: {item}, 남은 세트: {my_set}")
# 가능한 출력 1: 반환된 값: 10, 남은 세트: {20, 30}
# 가능한 출력 2: 반환된 값: 20, 남은 세트: {10, 30}
3. "어디에나 붙는" 것처럼 보이는 이유
우리가 pop() 을 쓰면서 "인스턴스 메서드" 같다. 라고 생각하는 것은 정확합니다. pop()은 실제로 각 객체(인스턴스)에 속한 메서드입니다.
obj.pop()처럼 보인다고 해서 pop()이 전역 함수이거나 모든 객체의 부모 클래스에 정의된 것은 아닙니다. 파이썬은 obj.method()를 호출할 때, obj라는 객체가 method라는 이름의 속성(메서드)을 가지고 있는지 동적으로 확인합니다.
-
my_list는list클래스의 인스턴스이고,list클래스에는pop이 정의되어 있습니다. -
my_dict는dict클래스의 인스턴스이고,dict클래스에도pop이 정의되어 있습니다.
따라서 my_list.pop()과 my_dict.pop()이 모두 작동하는 것입니다.
만약 pop() 메서드를 정의하지 않은 객체에서 호출을 시도하면 어떻게 될까요? 예상대로 AttributeError가 발생합니다. 튜플을 예를 들어 보겠습니다.
# 튜플(tuple)은 항목을 변경할 수 없으므로 pop() 메서드가 없습니다.
my_tuple = (1, 2, 3)
# AttributeError: 'tuple' object has no attribute 'pop'
my_tuple.pop()

요약
-
pop()은 파이썬의 전역 함수나 공통 메서드가 아닙니다. -
list,dict,set등 각각의 컨테이너 클래스가 개별적으로 정의한 메서드입니다. -
이름이 같은 이유는 "데이터를 꺼내고 반환한다"는 관습적인(convention) 의미를 공유하기 때문입니다.
-
동작 방식은 클래스마다 다르므로,
list는 인덱스로,dict는 키로,set은 임의로 항목을 제거합니다.
댓글이 없습니다.