开发者

Python get instance from list based on instance variable

Given a list of instances, say clients I'm trying to pluck an item from the list based on the value of a single instance variable screenName. I know I can do this:

for client in clients:
  if client.screenName = search:
    return client
开发者_开发技巧

But is there a nicer way of doing this without the loop?

Thanks for your help :)


You can use filter

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


I would use list comprehensions. Suppose this is your Client class:

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

If I got this list of clients:

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

...I can get a list containing only the clients with a given name:

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

Now, just get the first - and assumedly only - element:

>>> [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'

This is pretty short and IMHO elegant but can be less efficient because the list comprehension will iterate over all the list. If you do want to avoid this overhead, you can get an generator instead of a new list using parenthesis instead of square brackets:

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

However, note that the next() method can be called just once.

HTH!


You could use a generator expression,

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

but not that you still looping, just in a different way.

Note: If no client satisfies the condition client.screenName == search then the above will raise a StopIteration exception. This is different than your for-loop, which falls out of the loop without returning anything.

Depending on your situation, raising an exception might be better than failing silently.

If you do not want a default value instead of a StopIteration exception, then you could use the 2-parameter version of next:

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


using a dictionary for this:

assuming this :

d[screeName] = client

you can just do this:

return d[search]  


If clients is a dict then you can just use clients[search]. If the order of elements in your list is important, then you can use an OrderedDict from collections.


Best discussion of this topic is on this link

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

This requires you define a generic find function which would work for all types of lists like thus:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜