根据实例变量从列表中获取Python实例
假设我有一个叫做 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