给定一个实例列表,假设clients
我试图根据单个实例变量的值从列表中提取一个项目screenName
。我知道我可以这样做:
for client in clients:
if client.screenName = search:
return client
但是没有循环有没有更好的方法呢?
谢谢你的帮助 :)
您可以使用filter
try:
filter(lambda client: client.screenName == search, clients)[0]
except IndexError:
# handle error. May be use a default value
我会使用列表推导。假设这是您的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()
方法只能调用一次。
!
您可以使用生成器表达式,
client=next(client for client in clients if client.screenName == search)
但并不是说你还在循环,只是以不同的方式。
注意:如果没有客户端满足条件client.screenName == search
,则上述将引发StopIteration
异常。这与 your 不同for-loop
,后者在不返回任何内容的情况下退出循环。
根据您的情况,引发异常可能比静默失败要好。
如果您不想要默认值而不是StopIteration
异常,则可以使用 2 参数版本next
:
client=next(client for client in clients if client.screenName == search,
default_value)
为此使用字典:
假设这个:
d[screeName] = client
你可以这样做:
return d[search]
如果clients
是 adict
那么你可以使用clients[search]
. 如果列表中元素的顺序很重要,那么您可以使用OrderedDict
from collections
。
这个话题的最佳讨论在这个链接上
return find(lambda client: client.screenName == search, clients)
这需要您定义一个通用的 find 函数,该函数适用于所有类型的列表,如下所示:
def find(f, seq):
"""Return first item in sequence where f(item) == True."""
for item in seq:
if f(item):
return item