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

时间:2018-03-28 19:55:37

标签: python-3.x repr

如果我有一个名为Person的类,并且这个类包含每个人的姓名,年龄等,如果我用Person类填充一个列表,我想检查名称是否在列表中而不创建新的只是名字的列表。如果我使用 repr 并返回repr(self.name),我可以打印列表并让它返回列表中每个人的名字列表。如果我然后检查是否" steve"在列表中它返回False。我猜这是因为它正在比较"史蒂夫"每个班级,而不是班级 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)

2 个答案:

答案 0 :(得分:1)

使用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

答案 1 :(得分:1)

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

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

您还可以使用布隆过滤器快速确定列表中的'steve'是否,但如果不检查列表,则无法确定。你也可以使用像B-Tree这样的东西来快速执行这个检查(最坏的情况就像O(m),其中m是你正在寻找的字符串的长度)。

如果你不想要花哨的数据结构并且更喜欢pythonic ......那么,使用一个set,它将为你提供非常高性能的in检查(几乎是恒定时间):< / p>

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

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

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