如果我定义了以下内容:
header_text = self.browser.find_element_by_tag_name('h1').text
self.assertIn('To-do', header_text) # >>> OK
如何在没有定义Card = namedtuple('Card', ['rank', 'suit'])
class CardDeck():
ranks = [str(x) for x in range(2, 11)] + list('JQKA')
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self._cards = [Card(rank, suit) for rank in self.ranks for suit in self.suits]
def __getitem__(self, index):
return self._cards[index]
dunder方法的情况下支持in
运算符。例如以下内容:
__contains__
将输出:
deck = CardDeck()
print(Card('2', 'hearts') in deck)
有什么想法吗?
答案 0 :(得分:3)
__contains__
或__iter__
method可用时, __getitem__
用作后备。请参见表达式参考文档的Membership test operations section:
最后,尝试使用旧式的迭代协议:如果一个类定义了
__getitem__()
,则当且仅当存在非负整数索引时,x in y
才是True
i 使得x is y[i] or x == y[i]
且没有更低的整数索引会引发IndexError
异常。
所以实际上发生的是Python只是使用一个递增的索引,在Python中看起来像这样:
from itertools import count
def contains_via_getitem(container, value):
for i in count(): # increments indefinitely
try:
item = container[i]
if value is item or value == item:
return True
except IndexError:
return False
此处理方法扩展到所有迭代功能。未实现__iter__
但确实实现__getitem__
的容器仍可以为其创建一个迭代器(使用iter()
或等效的C-API):
>>> class Container:
... def __init__(self):
... self._items = ["foo", "bar", "baz"]
... def __getitem__(self, index):
... return self._items[index]
...
>>> c = Container()
>>> iter(c)
<iterator object at 0x1101596a0>
>>> list(iter(c))
['foo', 'bar', 'baz']
通过迭代进行的容器测试当然不是很有效。如果有一种方法可以在不进行全面扫描的情况下确定容器中是否有物品,请实施__contains__
方法以提供更好的实现!
对于卡片组,我可以想象一下,当项目为True
实例时简单地返回Card
就足够了(只要Card
类可以验证rank和suit参数):< / p>
def __contains__(self, item):
# a card deck contains all possible cards
return isinstance(item, Card)
答案 1 :(得分:2)
object.__contains__(self, item) ...
For objects that don’t define __contains__(), the membership test
first tries iteration via __iter__(), then the old sequence iteration
protocol via __getitem__(),...