2011-04-13 97 views
2

給定一個實例列表,比如clients我試圖根據單個實例變量screenName的值從列表中提取項目。我知道我可以這樣做:Python根據實例變量從列表中獲取實例

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

但是,有沒有更好的方式做到這一點沒有循環?

感謝您使用字典這個您的幫助:)

+2

我想你的意思是client.screen ==搜索 – 2011-04-13 20:32:41

回答

6

您可以使用filter

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

如果客戶端中的** no **客戶端具有'screenName == search',這會不會引發'IndexError'? ... – neurino 2011-04-13 20:44:37

+0

@neurino我認爲這種異常會被處理。但爲了完整起見,添加了「try-except」塊。 – 2011-04-13 20:58:05

+0

我只是刪除'[0]'並返回一個結果列表。畢竟可以有多個匹配,那麼如果只有第一個匹配... – neurino 2011-04-13 21:06:28

0

假設這樣的:

d[screeName] = client 

你可以這樣做:

return d[search] 
0

如果clients是一個dict然後你可以只使用clients[search]。如果列表中元素的順序很重要,則可以使用collections中的OrderedDict

1

我會用list comprehensions。假設這是你的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()方法可以只調用一次。

HTH!

+0

非常簡潔和不錯。我假設如果l包含多個具有相同screenName的對象,可以多次調用next()。 – Daniel 2015-06-15 07:55:04

1

你可以使用一個generator expression

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

但不是說你還是循環,只是以不同的方式。

注意:如果沒有客戶滿足條件client.screenName == search那麼上述將引起StopIteration例外。這與你的for-loop不同,它不會返回任何東西而退出循環。

根據你的情況,提出異常可能比靜靜地失敗更好。

如果你不想默認值,而不是StopIteration例外,那麼你可以使用的next 2參數版本:

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

最佳這個話題討論的是對這個link

return find(lambda client: client.screenName == search, clients) 

這需要你定義一個通用的查找功能這將對於所有類型的列表像這樣的工作:

def find(f, seq): 
    """Return first item in sequence where f(item) == True.""" 
    for item in seq: 
    if f(item): 
     return item 
+0

我想你的意思是's/find/filter /'? – 2011-04-13 20:40:26

+0

不,我的意思是我寫的,不要得到downvote。看到這裏:http://tomayko.com/writings/cleanest-python-find-in-list-function – Yasser 2011-04-13 20:44:27

+0

以及你應該在你的答案..定義'發現.. ..但是.. – Ant 2011-04-13 20:51:45