python中的容器与自定义容器
在Python中,容器(Container)是用于存储和组织其他对象的对象。Python提供了多种内置容器类型,同时也允许开发者创建自定义容器类型。
一、内置容器
1.常见的内置容器
(1). 列表 (list)
可变序列,有序集合
支持索引、切片、修改
my_list = [1, "hello", 3.14]
my_list[0] = 100 # 修改元素
(2). 元组 (tuple)
不可变序列,有序集合
创建后无法修改元素
my_tuple = (1, "world", 2.71)
# my_tuple[0] = 100 # 错误!不可修改
(3). 字典 (dict)
键值对映射,无序集合
键必须是不可变类型(如字符串、数字、元组)
my_dict = {"name": "Alice", "age": 30}
print(my_dict["name"]) # 输出: Alice
(4). 集合 (set)
无序不重复元素集
支持数学集合运算(并集、交集等)
my_set = {1, 2, 3, 2} # 自动去重: {1, 2, 3}
(5).字符串(String)
字符序列(虽然主要用于文本处理,但也是容器)
2.内置容器的常见操作
(1). 通用容器操作
所有容器类型都支持以下操作:
# 成员测试
x in container # 判断元素是否存在
x not in container # 判断元素是否不存在# 长度
len(container) # 获取容器中元素数量# 迭代
for item in container: # 遍历容器元素print(item)
(2). 序列类型(List, Tuple, String)特有操作
# 索引访问
container[index] # 获取指定位置的元素# 切片
container[start:stop:step] # 获取子序列# 连接
container1 + container2 # 序列连接# 重复
container * n # 序列重复n次
3. 可变序列(List)特有操作
# 修改元素
container[index] = value # 修改指定位置的元素# 切片赋值
container[start:stop] = [values] # 修改子序列# 添加元素
container.append(item) # 末尾添加
container.extend(iterable) # 扩展多个元素
container.insert(index, item) # 指定位置插入# 删除元素
del container[index] # 删除指定位置元素
container.remove(item) # 删除第一个匹配项
container.pop([index]) # 删除并返回指定位置元素(默认最后一个)# 排序和反转
container.sort() # 原地排序
container.reverse() # 原地反转
二、自定义容器
在 Python 里,除了使用列表、元组、字典等内置容器外,还能通过自定义类的方式创建符合特定需求的容器。
1. 基本概念
自定义容器意味着创建一个类,让这个类的实例能像内置容器(如列表、字典)一样进行操作,例如添加元素、删除元素、迭代等。为了实现这些功能,需要在类中实现一些特殊方法(也称为魔术方法)。
2.实现自定义容器所需的特殊方法
(1).__init__
方法
这是类的构造函数,用于初始化容器的状态。
class MyContainer:def __init__(self):self.items = []
(2).__len__
方法
该方法用于返回容器中元素的数量,当使用 len()
函数作用于容器实例时会调用此方法。
class MyContainer:def __init__(self):self.items = []def __len__(self):return len(self.items)container = MyContainer()
print(len(container)) # 输出: 0
(3).__getitem__
方法
通过该方法可以使用索引来访问容器中的元素,就像使用 []
操作符一样。
class MyContainer:def __init__(self):self.items = []def __getitem__(self, index):return self.items[index]def add_item(self, item):self.items.append(item)container = MyContainer()
container.add_item(10)
container.add_item(20)
print(container[0]) # 输出: 10
(4).__setitem__
方法
此方法用于通过索引来设置容器中元素的值。
class MyContainer:def __init__(self):self.items = []def __getitem__(self, index):return self.items[index]def __setitem__(self, index, value):self.items[index] = valuedef add_item(self, item):self.items.append(item)container = MyContainer()
container.add_item(10)
container[0] = 20
print(container[0]) # 输出: 20
(5).__delitem__
方法
用于通过索引删除容器中的元素。
class MyContainer:def __init__(self):self.items = []def __getitem__(self, index):return self.items[index]def __setitem__(self, index, value):self.items[index] = valuedef __delitem__(self, index):del self.items[index]def add_item(self, item):self.items.append(item)container = MyContainer()
container.add_item(10)
del container[0]
print(len(container)) # 输出: 0
(6). __contains__
方法
当使用 in
操作符检查元素是否在容器中时,会调用此方法。
class MyContainer:def __init__(self):self.items = []def __contains__(self, item):return item in self.itemsdef add_item(self, item):self.items.append(item)container = MyContainer()
container.add_item(10)
print(10 in container) # 输出: True
(7).__iter__
和 __next__
方法(迭代器协议)
__iter__
方法返回一个迭代器对象,通常就是容器对象本身。__next__
方法用于返回迭代器的下一个元素,当没有更多元素时,需要抛出StopIteration
异常。
class MyContainer:def __init__(self):self.items = []self.index = 0def __iter__(self):return selfdef __next__(self):if self.index < len(self.items):result = self.items[self.index]self.index += 1return resultelse:self.index = 0raise StopIterationdef add_item(self, item):self.items.append(item)container = MyContainer()
container.add_item(10)
container.add_item(20)
for item in container:print(item) # 依次输出: 10, 20
3.示例
示例一:自定义字典容器
class MyDictContainer:def __init__(self):self.data = {}def __getitem__(self, key):return self.data.get(key)def __setitem__(self, key, value):self.data[key] = valuedef __delitem__(self, key):if key in self.data:del self.data[key]def __contains__(self, key):return key in self.datadef __len__(self):return len(self.data)def __iter__(self):return iter(self.data)my_dict = MyDictContainer()
my_dict['name'] = 'Alice'
my_dict['age'] = 25
print(my_dict['name']) # 输出: Alice
print('age' in my_dict) # 输出: True
del my_dict['age']
print(len(my_dict)) # 输出: 1
for key in my_dict:print(key) # 输出: name
示例二:自定义序列类
class MySequence:def __init__(self, items):self._items = list(items)def __len__(self):return len(self._items)def __getitem__(self, index):return self._items[index]def __setitem__(self, index, value):self._items[index] = valuedef __str__(self):return str(self._items)# 使用示例
seq = MySequence([10, 20, 30])
print(seq[1]) # 输出: 20
seq[1] = 99 # 修改元素
print(seq) # 输出: [10, 99, 30]
三.自定义容器继承内置容器
在 Python 中,自定义容器可以通过继承内置容器(如 list
、dict
、set
等)来实现,这样可以复用内置容器的大部分功能,同时根据需求添加或修改特定的行为。以下分别介绍继承不同内置容器的示例及相关要点。
1.继承 list
实现自定义容器
class CustomList(list):def __init__(self, *args):super().__init__(*args)def append_unique(self, item):"""添加元素,但仅在元素不在列表中时添加"""if item not in self:self.append(item)return selfdef get_average(self):"""计算列表中所有数值元素的平均值"""if not self:return 0total = sum(num for num in self if isinstance(num, (int, float)))count = sum(isinstance(num, (int, float)) for num in self)return total / count if count > 0 else 0# 使用自定义列表
custom_list = CustomList([1, 2, 3])
custom_list.append_unique(4)
custom_list.append_unique(2) # 不会重复添加
print(custom_list) # 输出: [1, 2, 3, 4]
print(custom_list.get_average()) # 输出: 2.5
要点解释:__init__
方法:通过 super().__init__(*args)
调用父类 list
的初始化方法,确保自定义列表能像普通列表一样初始化。
自定义方法:append_unique
方法用于添加唯一元素,get_average
方法用于计算列表中数值元素的平均值。这些方法是在继承 list
原有功能基础上的扩展。
2.继承 dict
实现自定义容器
class CustomDict(dict):def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)def get_default(self, key, default=0):"""获取键对应的值,如果键不存在则返回默认值,同时将默认值存入字典"""value = self.get(key, default)if key not in self:self[key] = defaultreturn value# 使用自定义字典
custom_dict = CustomDict({'a': 1, 'b': 2})
print(custom_dict.get_default('a')) # 输出: 1
print(custom_dict.get_default('c')) # 输出: 0
print(custom_dict) # 输出: {'a': 1, 'b': 2, 'c': 0}
要点解释:__init__
方法:同样通过 super().__init__(*args, **kwargs)
调用父类 dict
的初始化方法。
自定义方法:get_default
方法类似于 dict
的 get
方法,但会在键不存在时将默认值存入字典。
继承 set
实现自定义容器:
class CustomSet(set):def __init__(self, *args):super().__init__(*args)def add_all(self, iterable):"""批量添加元素"""for item in iterable:self.add(item)return self# 使用自定义集合
custom_set = CustomSet([1, 2, 3])
custom_set.add_all([3, 4, 5])
print(custom_set) # 输出: {1, 2, 3, 4, 5}
要点解释:__init__
方法:调用父类 set
的初始化方法。
自定义方法:add_all
方法用于批量添加元素,方便一次性处理多个元素的添加操作。
注意:
方法覆盖:在继承内置容器时,可以覆盖父类的方法,但要谨慎操作,确保不会破坏原有的功能逻辑。
性能考虑:虽然继承内置容器可以复用很多功能,但在某些情况下,自定义的操作可能会影响性能,需要进行性能测试和优化。
兼容性:要注意自定义容器与 Python 标准库和其他代码的兼容性,确保自定义容器的行为符合预期。
三.关键方法实现容器行为
方法 | 作用 | 对应操作 |
---|---|---|
__len__(self) | 返回长度 | len(obj) |
__getitem__(self, key) | 获取元素 | obj[key] |
__setitem__(self, key, value) | 设置元素 | obj[key] = value |
__delitem__(self, key) | 删除元素 | del obj[key] |
__contains__(self, item) | 成员检查 | item in obj |
__iter__(self) | 返回迭代器 | for x in obj |
__reversed__(self) | 反向迭代 | reversed(obj) |
四、继承抽象基类 (ABC)
Python 的 collections.abc
模块提供了抽象基类,可确保自定义容器实现必要方法:
from collections.abc import MutableSequenceclass CustomList(MutableSequence):def __init__(self, data):self._data = list(data)def __len__(self):return len(self._data)def __getitem__(self, index):return self._data[index]def __setitem__(self, index, value):self._data[index] = valuedef __delitem__(self, index):del self._data[index]def insert(self, index, value):self._data.insert(index, value)
总结
内置容器:
list
,tuple
,dict
,set
等满足大部分需求。自定义容器:通过实现特殊方法(如
__getitem__
)创建定制化容器。抽象基类:使用
collections.abc
确保容器行为一致性。
通过灵活组合这些特性,可以构建适合特定场景的高效数据结构。