简体   繁体   English

Python *list*“in”运算符:相等、哈希检查还是身份?

[英]Python *list* "in" operator: equality, hash checking, or identity?

Those in the comments have asked me to provide my actual code, so I've removed the old example.评论中的人要求我提供我的实际代码,因此我删除了旧示例。

I'm making this , and I want two Page s with equal titles to compare equal.我正在做这个,我希望两个具有相同标题的Page s 比较相等。 I've done this to the Page class:我已经对 Page 类做了这个:

def __eq__(self, other):
    return self.title == other.title

but if I do this, it isn't True:但如果我这样做,那就不是真的:

>>> import mw_api_client as mwc
>>> w = mwc.Wiki('https://en.wikipedia.org/w/api.php')
>>> a = [w.page(str(i)) for i in range(20)]
>>> w.page('0') in a
False

How can I make this True?我怎样才能做到这一点?

The __contains __ method for lists is documented in the 'membership tests` section here:用于列表的__contains __方法记录在此处的“成员资格测试”部分:

https://docs.python.org/3.6/reference/expressions.html#membership-test-details https://docs.python.org/3.6/reference/expressions.html#membership-test-details

For container types such as list, tuple, set, frozenset, dict, or collections.deque, the expression x in y is equivalent to any(x is e or x == e for e in y) .对于列表、元组、集合、冻结集、字典或 collections.deque 等容器类型x in y的表达式x in y等效于any(x is e or x == e for e in y)

For your specific use case, you need to override __contains__ - however you can't just override __contains__ on the list - eg:对于您的特定用例,您需要覆盖__contains__ - 但是您不能只覆盖列表中的__contains__ - 例如:

a = []
a.__contains__ = lambda: True
AttributeError: 'list' object attribute '__contains__' is read-only

The solution therefore is to create a custom class that wraps the list, and provides it's own __contains__ method.因此,解决方案是创建一个包装列表的自定义类,并提供它自己的__contains__方法。 Something like the following (note I'm using dicts, hence obj['title'] rather than obj.title in this example - you might also want to test more things in __contains__ such as type comparison etc).类似于以下内容(请注意,我使用的是 dicts,因此在此示例中使用obj['title']而不是obj.title - 您可能还想在__contains__测试更多内容,例如类型比较等)。 I'm using UserList here since it provides a nice list class to inherit from, and makes the list contents available in data :我在这里使用UserList因为它提供了一个很好的list类来继承,并使列表内容在data可用:

from collections import UserList

class MyList(UserList):
    def __init__(self, lst):
        self.data = lst

    def __contains__(self, obj):
        """Return True if any item in the list has a title, and the title matches that of the passed-in dict"""
        return any(obj['title'] == x['title'] for x in self.data if 'title' in x)

mr = {"title": "mr"}
mrs = {"title": "mrs"}
dr = {"title": "dr"}
random = {"foo": "bar"}


x = [mr, mrs, random]

y = MyList(x)

print(mr in y) # True
print(dr in y) # False
y.append(dr)
print(dr in y) # True

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM