【问题标题】:Accessing object with specific attribute in list访问列表中具有特定属性的对象
【发布时间】:2020-01-21 18:08:23
【问题描述】:

假设我有一个保存员工信息的对象列表:

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

employees = [Employee('Alice'), 
             Employee('Bob'), 
             Employee('Catherine'), 
             Employee('David')]

每个对象都会有更多的属性,也会有更多的员工,但这被简化了。现在我想访问 Catherine 的 Employee 对象。有没有一种蟒蛇方式来获取凯瑟琳的对象?我知道我可以将对象存储在字典中,并以它们的名称作为键,但这似乎是多余的。

我可以使用[i for i in employees if i.name=='Catherine'] 之类的列表解析,但我想知道是否有更精确的方法,可以访问具有特定、唯一属性的员工,而无需搜索所有员工。

【问题讨论】:

  • 你需要一个不同的数据结构来保存它们,比如dict。这样,key 可以是唯一的属性,比如name,value 是实例
  • 这就是为什么dict 不是多余的;它提供了对象列表本身没有的索引。
  • "I know I could store the objects in a dictionary with their name as a key, but that seems redundant" 比每次都迭代整个列表的冗余要少得多
  • 是的,dict 方法确实是您想要的,因为只有这样您才能“访问特定的唯一属性”
  • 打个比方,在这里使用字典而不是列表并不比书后的索引更“冗余”,它列出了书中使用的你可能想要的单词查找,以及它们出现的页码。严格意义上来说,额外的信息是“冗余的”,如果这些页面被从书中撕下,您将能够从其他页面的信息中重建它们。但从某种意义上说,索引可以用于其他页面无法达到的目的,这并不是“冗余”;有效地找到使用单词的页面。

标签: python python-3.x oop


【解决方案1】:

这正是“next”的用途,它将以列表理解式格式返回第一个肯定结果。如果找不到,它将引发 StopIteration 异常。您可以通过将理解包装在括号中并提供第二个参数来添加默认值。

next(i for i in employees if i.name=='Catherine')

https://docs.python.org/3/library/functions.html#next

【讨论】:

  • 但它仍然需要查看列表中的每个实例。只需使用名称为键的字典
  • 最有效的方法是dict(毕竟,如果你只需要任意顺序的值,你总是可以使用dict.values())。这是效率第二高的,并且充当短路列表理解。好主意。
  • 有时使用迭代器,有时使用字典。如果有重复的键,而您只关心第一个键怎么办?或者如果键是多个值的复合物怎么办?在较小的数据集中,O(n) 查找是微不足道的,没有理由不使用这种方法。
  • @OsmosisJonesLoL 不,他们没有使用字典明确说明。 OP 写道,他们认为这是多余的,但实际上并非如此。
  • @schwartz721 比较 d = {name: Employee(name) for name in ['Alice', 'Bo']}d = {'Alice': Employee('Alice'), 'Bob': Employee('Bob')}。您构造 dict 的方式可以与dict 本身分开考虑。
【解决方案2】:

是的,你可以,这取决于你如何实现__eq__ dunder 方法......这会起作用

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

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


employees = [Employee('Alice'),
             Employee('Bob'),
             Employee('Catherine'),
             Employee('David')]
print("Alice" in employees)

这会输出

True

【讨论】:

  • 这仍然需要对整个列表进行迭代,只是从语句中看起来不像
  • OP 想要实例,而不是 TrueFalse
猜你喜欢
  • 1970-01-01
  • 2013-01-28
  • 1970-01-01
  • 2010-11-23
  • 1970-01-01
  • 2013-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多