Python __contains__ 方法
最后修改于 2025 年 4 月 8 日
这份全面的指南探讨了 Python 的 __contains__
方法,这是一个实现成员资格测试操作的特殊方法。我们将涵盖基本用法、自定义容器、性能考虑和实践示例。
基本定义
__contains__
方法实现了成员资格测试运算符(in
和 not in
)。如果项目在容器中,它应该返回 True
,否则返回 False
。
主要特征:它接受一个参数(要测试的项目),可以在任何类中定义,并且在使用 in
运算符时自动调用。 它为用户定义的对象启用自定义包含逻辑。
基本 __contains__ 实现
这是一个简单的实现,展示了 __contains__
如何与 in
运算符一起工作。此示例检查列表中是否存在成员。
class MyContainer: def __init__(self, items): self.items = items def __contains__(self, item): return item in self.items container = MyContainer([1, 2, 3, 4, 5]) print(3 in container) # True print(6 in container) # False
此示例演示了基本模式。 __contains__
方法委托给底层列表的包含检查。 in
运算符自动调用此方法。
该方法返回一个布尔值,指示该项目是否存在于容器中。 这个简单的实现反映了 Python 内置的列表行为。
自定义成员资格逻辑
__contains__
允许实现超出简单值检查的自定义成员资格测试逻辑。 在这里,我们检查偶数。
class EvenNumbers: def __contains__(self, num): return isinstance(num, int) and num % 2 == 0 evens = EvenNumbers() print(4 in evens) # True print(5 in evens) # False print("a" in evens) # False
此实现不存储数字,而是定义了构成数学成员资格的条件。 它检查输入是否为整数且为偶数。
该示例展示了 __contains__
如何在没有实际存储的情况下实现抽象包含规则。 这种模式对于虚拟容器很有用。
不区分大小写的字符串容器
此示例演示了一个字符串容器,该容器执行不区分大小写的成员资格测试,这对于大小写规范化场景很有用。
class CaseInsensitiveContainer: def __init__(self, items): self.items = [item.lower() for item in items] def __contains__(self, item): return item.lower() in self.items fruits = CaseInsensitiveContainer(['Apple', 'Banana', 'Orange']) print('apple' in fruits) # True print('BANANA' in fruits) # True print('pear' in fruits) # False
该容器存储所有项目的小写版本,并在检查之前将搜索词转换为小写。 这确保了大小写不会影响成员资格测试。
当您需要不区分大小写的查找,但又想保留存储项目的原始大小写以供显示时,此模式很有用。
基于范围的包含
此示例实现了一个容器,该容器检查数字是否在其任何存储的范围内,从而演示了复杂的包含逻辑。
class RangeContainer: def __init__(self, ranges): self.ranges = ranges def __contains__(self, num): return any(start <= num <= end for start, end in self.ranges) ranges = RangeContainer([(1, 5), (10, 15), (20, 25)]) print(3 in ranges) # True print(8 in ranges) # False print(22 in ranges) # True
该容器存储表示范围的元组。 __contains__
方法使用带有 any()
的生成器表达式检查数字是否在这些范围中的任何一个范围内。
此实现有效地处理多个不连续的范围,而无需存储每个可能的值,从而使其在大型范围内具有内存效率。
使用 __contains__ 进行性能优化
此示例展示了 __contains__
如何通过使用集合进行 O(1) 查找而不是 O(n) 列表搜索来优化成员资格测试。
class OptimizedContainer: def __init__(self, items): self.items = list(items) self.items_set = set(items) def __contains__(self, item): return item in self.items_set large_data = OptimizedContainer(range(1000000)) print(999999 in large_data) # Fast lookup print(-1 in large_data) # Fast negative result
该类维护一个列表(用于有序访问)和一个集合(用于快速成员资格测试)。 __contains__
方法使用该集合进行恒定时间查找。
当您需要有序迭代和频繁的成员资格测试时,此模式很有价值。 内存开销可以通过性能提升来证明。
最佳实践
- 返回布尔值: 应该返回 True 或 False,而不是其他类型
- 考虑性能: 针对预期的使用模式进行优化
- 保持一致性: 行为应与其他容器方法匹配
- 处理边缘情况: 决定如何处理 None、NaN 或其他特殊值
- 记录行为: 明确指定构成成员资格的条件
资料来源
作者
列出所有 Python 教程。