根据实例变量从列表中获取Python实例

2 投票
6 回答
3775 浏览
提问于 2025-04-16 15:41

假设我有一个叫做 clients 的实例列表,我想根据其中一个实例的变量 screenName 的值来找出一个特定的项目。我知道我可以这样做:

for client in clients:
  if client.screenName = search:
    return client

但是有没有更简单的方法可以做到这一点,而不需要用循环呢?

谢谢你的帮助 :)

6 个回答

1

我会使用列表推导式。假设这是你的Client类:

>>> class Client:
...    def __init__(self, screenName):
...        self.screenName = screenName

如果我有这个客户列表:

>>> l = [Client('a'), Client('b'), Client('c')]

...我可以得到一个只包含特定名字客户的列表:

>>> [e for e in l if e.screenName == 'b']
[<__main__.Client instance at 0x2e52b0>]

现在,只需获取第一个 - 也就是唯一的 - 元素:

>>> [e for e in l if e.screenName == 'b'][0]
<__main__.Client instance at 0x2e52b0>
>>> c = [e for e in l if e.screenName == 'b'][0]
>>> c.screenName
'b'

这个方法相对简短,而且我觉得很优雅,但可能效率较低,因为列表推导式会遍历整个列表。如果你想避免这种额外的开销,可以用圆括号而不是方括号来获取一个生成器,而不是一个新的列表:

>>> g = (e for e in l if e.screenName == 'b')
>>> g
<generator object <genexpr> at 0x2e5440>
>>> g.next()
<__main__.Client instance at 0x2e52b0>

不过,请注意,next()方法只能调用一次。

希望这对你有帮助!

1

你可以使用一个生成器表达式

client=next(client for client in clients if client.screenName == search)

不过要注意,你还是在循环,只是方式不同而已。

注意:如果没有任何客户端满足条件client.screenName == search,那么上面的代码会抛出一个StopIteration异常。这和你的for循环不同,后者在没有满足条件时会直接跳出循环,而不会返回任何东西。

根据你的情况,抛出异常可能比静默失败要好。

如果你不想要一个默认值来代替StopIteration异常,那么你可以使用next的两个参数版本:

client=next(client for client in clients if client.screenName == search, 
            default_value)
5

你可以使用 filter

try:
    filter(lambda client: client.screenName == search, clients)[0]
except IndexError:
    # handle error. May be use a default value

撰写回答