我无法理解 python 中的 __contains__ 方法
Posted
技术标签:
【中文标题】我无法理解 python 中的 __contains__ 方法【英文标题】:I am having trouble understanding the __contains__ method in python 【发布时间】:2016-09-10 02:37:30 【问题描述】:我已经建立了一个简单的类,叫做 Cell
class Cell:
def __init__(self, letter):
self.letter = letter
if letter == 'A' or letter == 'E' or letter == 'I' or letter == 'O' or letter == 'U' or letter == 'L' or letter == 'N' or letter == 'S' or letter == 'T' or letter == 'R':
self.points = 1
elif letter == 'D' or letter == 'G':
self.points = 2
elif letter == 'B' or letter == 'C' or letter == 'M' or letter == 'P':
self.points = 3
elif letter == 'F' or letter == 'H' or letter == 'V' or letter == 'W' or letter == 'Y':
self.points = 4
elif letter == 'K':
self.points = 5
elif letter == 'J' or letter == 'X':
self.points = 8
elif letter == 'Q' or letter == 'Z':
self.points = 10
else:
self.points = 0
现在我正在尝试为该类编写一个__contains__
方法,因此如果我有一个单元格数组,我可以检查数组中是否包含某个字母的单元格
Tiles = []
Tiles.append(Cell("A")
Tiles.append(Cell("B")
Tiles.append(Cell("C")
Tiles.append(Cell("D")
Cell("A") in Tiles
应该返回 True
但是我对如何去做这件事感到困惑,并且在网上或 python 文档中几乎没有找到帮助
【问题讨论】:
【参考方案1】:我正在尝试为该类编写一个
__contains__
方法
不,你不是。这是你在implementing a container 时要问的问题,而不是被收容的东西。
您不会对如何实现__contains__
感到困惑——您只需在容器 上实现该功能,在本例中就是列表。您对 contains 的工作原理感兴趣。
您需要实现__eq__
(以及__hash__
和__ne__
,为了更好的衡量标准)
我认为这是说明性的:
class Cell:
def __init__(self, thing):
self.thing = thing
def __eq__(self, other):
return other.thing == self.thing
a = [Cell(1)]
print Cell(1) in a
这里有更完整的例子:Elegant ways to support equivalence ("equality") in Python classes
我没有看到关于 list contains 如何准确工作的参考,但参考实现在 line 437 here;基本上它遍历列表并检查提供的项目是否等于列表中的任何项目。
这就是我们通过重载 __eq__
来重载“==
”等式运算符的原因。
当然,这个过程是O(n)
(所花费的时间与列表中的项目数量成正比——在最坏的情况下我们必须检查每一个)。字典或集合可以在O(1)
“恒定”时间内执行此操作,但这需要将输入作为键进行散列。出于这个原因,通常习惯于在重载相等时重载散列函数,以免出现意外行为。 __ne__
是 python 的“不等于”运算符。 Overload this too
【讨论】:
别忘了__ne__
。
集合也是一个没有值的字典,可以在恒定时间内查找可散列值。
谢谢,这是一个很好的答案。我唯一的问题是,如果我正在实现eq
和ne
,为什么我需要实现__hash__
函数
@JamesNotaro 对于列表,您不需要,但对于任何散列其内容的数据结构(如字典或集合),“容器中的单元格(1)”将是散列单元格(1) ,并检查该哈希值是否在容器中。在这种情况下,即使 Cell(1) 与结构中的某些内容等于,因为它的哈希值不匹配,你会得到它不包含【参考方案2】:
如果s
是一个序列,那么m in s
返回一个bool
。现在,当type(s)
类实现__contains__
方法时,s
也可以是sequence-like。
因此obj in Tiles
与obj
的成员资格无关,而是在Tiles
列表中。
其次,为什么Cell('A') in Tiles
在添加一个之前返回False
?因为它们是不同的对象。通过实现__eq__
方法,您可以引入新的语义,说明它们在满足某某时相同。
x = Cell('A')
y = Cell('A')
x is y # False, same as id(x) == id(y)
x == y # don't really know what that means
# now enriching semantics by __eq__
x == y # True/ False
如果要将这些对象用作键,则应实现 __hash__
函数。但有一些警告。检查文档。
【讨论】:
以上是关于我无法理解 python 中的 __contains__ 方法的主要内容,如果未能解决你的问题,请参考以下文章
请问python描述符property中的self.fget(instance)怎么理解