python __contains__

1. __contains__ 方法简介
在 Python 中,__contains__ 是一个魔术方法(或称为特殊方法,magic method 或 dunder method),用于检查一个对象是否包含某个特定元素。这个方法通常与 in 关键字一起使用来判断一个对象是否包含某个值。
__contains__ 方法定义在对象的类中,用于定制 in 运算符的行为。当我们在一个对象上使用 in 运算符时,实际上是调用了对象的 __contains__ 方法。
下面是调用 in 运算符的一般语法:
element in object
其中,object 是一个可迭代的对象,element 是我们要检查的特定元素。当 element 存在于 object 中时,运算符返回 True,否则返回 False。
2. __contains__ 方法的使用
为了能够理解 __contains__ 方法的具体用法,让我们先来看一个简单的示例。
class MyList:
def __init__(self, data):
self.data = data
def __contains__(self, element):
return element in self.data
lst = MyList([1, 2, 3, 4, 5])
print(3 in lst) # 输出:True
print(6 in lst) # 输出:False
在上面的示例中,我们定义了一个名为 MyList 的类,该类接收一个参数 data,并将它保存在实例变量 self.data 中。然后,我们在 MyList 类中实现了 __contains__ 方法,用于判断某个元素是否存在于 self.data 中。
在这个示例中,我们创建了一个 MyList 的实例 lst,并将 [1, 2, 3, 4, 5] 赋值给 lst.data。然后,我们使用 in 运算符来检查 3 是否在 lst 中。
根据 __contains__ 方法的定义,当我们在 lst 对象上使用 in 运算符时,实际上是调用了 lst.__contains__(3) 方法。这个方法返回了 3 是否存在于 lst.data 中的布尔值。因此,上述代码输出了 True。
同样的方式,我们使用 6 作为参数,检查其是否存在于 lst 对象中。__contains__ 方法返回了 6 是否存在于 lst.data 中的布尔值,因此输出了 False。
如上所示,我们可以通过实现 __contains__ 方法来定制 in 运算符的行为,使对象表现得像一个集合,使得我们可以方便地检查一个元素是否存在于对象中。
3. 使用 __contains__ 方法实现自定义集合
接下来,我们将使用 __contains__ 方法来实现一个自定义的集合类 MySet,该类可以包含任意类型的元素,并允许我们使用 in 运算符来检查元素是否存在于集合中。
class MySet:
def __init__(self, data=None):
if data is None:
self.data = []
else:
self.data = list(data)
def __contains__(self, element):
return element in self.data
def add(self, element):
if element not in self.data:
self.data.append(element)
def remove(self, element):
if element in self.data:
self.data.remove(element)
def __str__(self):
return f"MySet({self.data})"
def __repr__(self):
return str(self)
s = MySet([1, 2, 3, 4, 5])
print(3 in s) # 输出:True
print(6 in s) # 输出:False
s.add(6)
s.add(7)
print(6 in s) # 输出:True
print(s) # 输出:MySet([1, 2, 3, 4, 5, 6, 7])
s.remove(4)
print(4 not in s) # 输出:True
print(s) # 输出:MySet([1, 2, 3, 5, 6, 7])
在上面的示例中,我们定义了一个名为 MySet 的集合类,该类包含了 __init__、__contains__、add、remove、__str__ 和 __repr__ 等方法。
__init__方法用于初始化集合对象,其中的参数data可以是一个可迭代的对象。如果data为None,则初始化一个空的集合,否则将data转换为列表并保存到self.data变量中。__contains__方法用于判断指定的元素是否存在于集合中。它实现了in运算符的功能。add方法用于将指定的元素添加到集合中,如果元素已存在,则不进行任何操作。remove方法用于从集合中移除指定的元素,如果元素不存在,则不进行任何操作。__str__和__repr__方法用于返回对象的字符串表示形式,其中__str__方法用于打印对象,而__repr__方法用于在交互式环境中显示对象。
通过实现上述方法,我们可以使用 in 运算符来检查元素是否存在于集合中,并可以使用 add 方法向集合中添加元素,使用 remove 方法从集合中移除元素。然后,我们还定义了 __str__ 和 __repr__ 方法来定制集合对象的字符串表示形式。
在上述示例中,我们首先创建了一个 MySet 对象 s,并初始化它为 [1, 2, 3, 4, 5]。然后,我们使用 in 运算符来检查 3 和 6 是否存在于 s 中,输出分别为 True 和 False。
接下来,我们使用 add 方法将 6 和 7 添加到 s 中,并再次使用 in 运算符检查 6 是否存在于 s,输出为 True。我们还打印了 s 对象,输出为 MySet([1, 2, 3, 4, 5, 6, 7])。
最后,我们使用 remove 方法从 s 中移除了 4,然后再次使用 in 运算符检查 4 是否存在于 s,输出为 True。我们还打印了 s 对象,输出为 MySet([1, 2, 3, 5, 6, 7])。
如上所示,通过实现 __contains__ 方法,我们可以在自定义的集合类中使用 in 运算符来检查元素是否存在于集合中,从而实现了类似于内置集合类的功能。这使得我们可以方便地使用 in 运算符来判断元素是否属于我们定义的集合。
4. 自定义对象的 __contains__ 方法
除了用于集合类,我们也可以在自定义的对象中实现 __contains__ 方法来定制对象的包含行为。下面是一个示例:
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def __contains__(self, point):
x, y = point
return 0 <= x < self.width and 0 <= y < self.height
rect = Rectangle(10, 5)
print((3, 4) in rect) # 输出:True
print((11, 4) in rect) # 输出:False
print((7, 6) in rect) # 输出:False
print((9, 4) in rect) # 输出:True
print((5, 0) in rect) # 输出:True
在上面的示例中,我们定义了一个名为 Rectangle 的矩形类,该对象具有 width 和 height 这两个属性。我们在 Rectangle 类中实现了 __contains__ 方法,用于判断给定的点 (x, y) 是否位于矩形的范围内。
在 __contains__ 方法中,我们检查给定的点的 x 坐标是否在矩形的宽度范围内,并且检查 y 坐标是否在矩形的高度范围内。如果两个条件都满足,则返回 True,表示该点在矩形内;否则返回 False,表示该点不在矩形内。
然后,我们创建了一个 Rectangle 对象 rect,宽度为 10,高度为 5。我们使用 in 运算符来检查一些点是否在矩形内,输出分别为 True 或 False。
通过实现 __contains__ 方法,我们可以定制对象的包含行为,使得我们可以方便地判断某个点是否在给定的矩形内。
5. 总结
本文详细介绍了 python 中的 __contains__ 方法,并给出了使用示例。__contains__ 方法是一个魔术方法,用于定制 in 运算符的行为,它定义了对象在使用 in 运算符时的操作行为。通过实现 __contains__ 方法,我们可以自定义对象的包含行为,使得我们可以方便地使用 in 运算符来判断对象是否包含某个特定元素。
我们通过一个简单的示例和一个自定义集合类的示例来说明了 __contains__ 方法的使用。在这些示例中,我们演示了如何使用 in 运算符来判断元素是否存在于对象中,以及如何添加和移除元素。
最后,我们还给出了一个使用 __contains__ 方法来实现自定义对象的示例,以展示如何定制对象的包含行为。
通过理解和熟悉 __contains__ 方法的使用,我们可以更好地利用 in 运算符,并根据实际需求定制对象的包含行为。这使得我们可以方便地检查元素是否存在于对象中,提供了更多的灵活性和定制化的功能。
极客教程