在日常python开发中,内置的list、dict、set等容器类型极大地方便了我们的数据管理。但如果业务出现特殊需求,标准容器无法胜任怎么办?此时就需要自定义容器,既能像内置类型一样用,也能实现个性化行为!今天带你由浅入深地掌握Python"自定义容器"的全部方法和核心原理。
一、什么是自定义容器?
自定义容器指的是:实现特定"容器协议"的自定义类,对象能像list/dict一样支持索引、for循环、len()、in、切片等操作。
你可以实现:
- 定长队列(缓存)
- 有效期缓存字典
- 只读/自定义校验的有序集合
- 支持自定义索引的数据结构
- "伪"list/"伪"dict等任意自定义数据行为
二、最基础的容器协议:__len__
、__getitem__
、__setitem__
示例:仿列表的自定义容器
python
class MyList:
def __init__(self, data=None):
self._data = list(data) if data else []
def __len__(self):
return len(self._data)
def __getitem__(self, idx):
print(f"访问索引 {idx}")
return self._data[idx]
def __setitem__(self, idx, value):
print(f"将{value}赋值到索引{idx}")
self._data[idx] = value
def append(self, value):
self._data.append(value)
python
ml = MyList([1, 2, 3])
print(len(ml)) # 3
print(ml[1]) # 访问索引 1 \n 2
ml[1] = 100 # 将100赋值到索引1
ml.append(200)
print(list(ml._data)) # [1, 100, 3, 200]
三、进阶协议:__iter__
, __contains__
和切片支持
__iter__
让你的容器支持for ... in ...
__contains__
支持in
判断
python
class MyList:
def __init__(self, data=None):
self._data = list(data) if data else []
def __len__(self):
return len(self._data)
def __getitem__(self, idx):
print(f"访问索引 {idx}")
return self._data[idx]
def __setitem__(self, idx, value):
print(f"将{value}赋值到索引{idx}")
self._data[idx] = value
def append(self, value):
self._data.append(value)
def __iter__(self):
return iter(self._data)
def __contains__(self, item):
return item in self._data
ml = MyList([1, 2, 3])
print(len(ml)) # 3
print(ml[1]) # 访问索引 1 \n 2
ml[1] = 100 # 将100赋值到索引1
ml.append(200)
print(list(ml._data)) # [1, 100, 3, 200]
for i in ml:
print(i)
print(100 in ml) # True
支持切片
要支持切片,需要同时处理 index
和 slice
:
python
def __getitem__(self, idx):
if isinstance(idx, slice):
print(f"访问切片 {idx}")
return MyList(self._data[idx])
return self._data[idx]
四、实现字典型容器协议:__setitem__
、__getitem__
、__delitem__
等
自定义dict-like结构:
python
class MyDict:
def __init__(self):
self._d = {}
def __setitem__(self, key, value):
self._d[key] = value
def __getitem__(self, key):
return self._d[key]
def __delitem__(self, key):
del self._d[key]
def __contains__(self, key):
return key in self._d
def keys(self):
return self._d.keys()
def items(self):
return self._d.items()
def values(self):
return self._d.values()
五、更高阶设计:自定义行为与约束
比如:只读容器、自动过滤、缓存等
python
class ReadOnlyList:
def __init__(self, data):
self._data = list(data)
def __getitem__(self, idx):
return self._data[idx]
def __len__(self):
return len(self._data)
def __setitem__(self, idx, value):
raise NotImplementedError("只读容器!")
def append(self, value):
raise NotImplementedError("只读容器!")
六、魔法方法一览表(小抄)
魔法方法 | 作用 |
---|---|
__len__ |
len(obj) |
__getitem__ |
obj[key] |
__setitem__ |
obj[key]=value |
__delitem__ |
del obj[key] |
__iter__ |
for x in obj |
__contains__ |
x in obj |
__reversed__ |
reversed(obj) |
如果你喜欢这篇文章,欢迎点赞、收藏和转发,更多Python干货内容敬请关注!