使用 repr 将字符串与对象列表进行比较

Comparing string to list of objects with repr

如果我有一个class叫Person,而这个class包含每个人的名字,年龄等,如果我用Personclass填一个列表我想要检查名称是否在列表中而不创建仅包含名称的新列表。如果我使用 repr 和 return repr(self.name),我可以打印列表并让它 return 每个人的名字列表在列表中。如果我然后检查 "steve" 是否在列表中,它 returns False。我猜这是因为它将 "steve" 与每个 class 进行比较,而不是 class repr。有没有办法在不创建新列表的情况下做到这一点?

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __repr__(self):
        return repr(self.name)

people = [Person('steve', 25), Person('dan', 30),Person('heather', 19)]
print(people)
print('steve' in people)

使用any():

any(p.name == 'steve' for p in people)
#True

...以及失败测试:

any(p.name == 'bob' for p in people)
#False

但是,要能够使用 in,您需要定义 __eq__,而不是 __repr__:

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __eq__(self, s):
        return s == self.name

现在它按预期工作了:

'steve' in people
#True

'bob' in people
#False

最简单的方法可能是手动执行此操作:

steve_in_people = any('steve' == repr(person) for person in people)

您也可以使用布隆过滤器快速确定 'steve' 是否不在您的列表中 ,但是如果不检查列表就无法确定.您还可以使用 B-Tree 之类的东西来非常快速地执行此检查(最坏的情况是 O(m) 之类的东西,其中 m 是您要查找的字符串的长度)。

如果你不想要花哨的数据结构并且更喜欢 pythonic... 那么,使用一个集合,它会给你非常 high-performance in 检查(实际上 constant-time):

names = {repr(person) for person in people}
steve_in_people = 'steve' in names

@JoeIddon 关于修改 class 以轻松支持此行为提出了一个很好的观点。我会建议进一步改进:

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return self.name

    def __eq__(self, s):
        return s == self.name

    # This will allow you to quickly find this object in a set using its name
    def __hash__(self):
        return hash(self.name)

现在您可以创建一组 Person 个对象并使用名称字符串搜索它:

person_set = set(all_person_objects)
steve_in_people = 'steve' in person_set