在使用 Python 时,你会发现自己使用 my_list.pop() 删除列表的最后一个项目,以及使用 my_dict.pop('key') 删除字典的项目等,在各种对象上使用 .pop()。
它给人一种 pop() 可以附加到任何对象上的 全能实例方法 的感觉。那么这个 pop() 方法究竟是什么呢?
1. 'pop()' 不是一个
简单来说,list 的 pop() 和 dict 的 pop() 实际上是 名称相同,但实际上完全不同的方法。
-
list类定义了适合列表的pop()方法。 -
dict类同样定义了适合字典的pop()方法。 -
set类也是如此。
不同对象拥有相同名称的方法与 Python 的面向对象特性之一的 多态性(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')(返回默认值 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() 是全局函数或在所有对象的父类中定义。 Python 在调用 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' 对象没有属性 'pop'
my_tuple.pop()

总结
-
pop()不是 Python 的全局函数或通用方法。 -
list、dict、set等 是各自容器类单独定义的方法。 -
名称相同的原因是因为它们共享 “提取并返回数据” 的 约定意义。
-
由于各类的操作方式不同,
list通过索引,dict通过键进行移除,而set则是任意移除项目。
目前没有评论。