如何通过属性从对象列表中选择对象(Python)

17 投票
4 回答
30941 浏览
提问于 2025-04-16 12:55

抱歉如果这个问题已经有人问过,但我觉得我不知道该用什么专业术语去谷歌搜索合适的解决方案。

我想从一个对象列表中,根据某个属性的值来选择一个对象,比如:

class Example():
    def __init__(self):
        self.pList = []
    def addPerson(self,name,number):
        self.pList.append(Person(self,name,number))

class Person():
    def __init__(self,name,number):
        self.nom = name
        self.num = number


a = Example()
a.addPerson('dave',123)
a.addPerson('mike',345)

a.pList #.... somehow select dave by giving the value 123

在我的情况下,这个数字总是唯一的。

谢谢大家的帮助。

4 个回答

3

你需要了解的术语是“映射”或者“字典”:这会引导你到Python文档中的正确页面

非常基础的例子:

>>> a = {123:'dave', 345:'mike'}
>>> a[123]
'dave'
6

如果这些名字是独一无二的标识符,而且你只打算通过这个独特的标识符来访问你的人员信息,那么使用字典确实是个不错的选择。

不过,如果你想随着时间的推移添加更多的属性,并且希望能够通过这些属性来查找一个或多个人员,那么你可能需要考虑一个更复杂的解决方案:

class Example():
    def __init__(self):
        self.__pList = []
    def addPerson(self,name,number):
        self.__pList.append(Person(name,number))
    def findPerson(self, **kwargs):
        return next(self.__iterPerson(**kwargs))
    def allPersons(self, **kwargs):
        return list(self.__iterPerson(**kwargs))
    def __iterPerson(self, **kwargs):
        return (person for person in self.__pList if person.match(**kwargs))

class Person():
    def __init__(self,name,number):
        self.nom = name
        self.num = number
    def __repr__(self):
        return "Person('%s', %d)" % (self.nom, self.num) 
    def match(self, **kwargs):
        return all(getattr(self, key) == val for (key, val) in kwargs.items())

假设我们有一个叫Mike的人和两个叫Dave的人。

a = Example()
a.addPerson('dave',123)
a.addPerson('mike',345)
a.addPerson('dave',678)

现在你可以通过编号来找到人员:

>>> a.findPerson(num=345)
Person('mike', 345)

或者通过名字来找到:

>>> a.allPersons(nom='dave')
[Person('dave', 123), Person('dave', 678)]

或者同时通过这两者来查找:

>>> a.findPerson(nom='dave', num=123)
Person('dave', 123)
21

一种选择是使用内置的 next() 函数:

dave = next(person for person in a.pList if person.num == 123)

如果没有找到任何东西,这个函数会抛出一个 StopIteration 的错误。你可以使用 next() 的两个参数形式,来为这种情况提供一个默认值:

dave = next(
    (person for person in a.pList if person.num == 123),
    None,
)

还有一种稍微详细一点的替代方法,就是使用 for 循环:

for person in a.pList:
    if person.num == 123:
        break
else:
    print "Not found."
    person = None
dave = person

撰写回答