Вот вариант ответа Седрика Жюльена, потому что он может потерпеть неудачу в некоторых (редких) случаях:
any(True for d in dev["devices"] if d['name'] == devName)
Вот (по общему признанию, необычный, но возможный) случай, который иллюстрирует, когда any(True …)
дает правильный результат, тогда как any(d …)
не дает:
>>> class special_dict(dict):
... def __nonzero__(self):
... return False # All special_dict objects are False
...
>>> dev = {'devices': [special_dict(name="DEVNAME") for _ in xrange(10)]}
>>> any(d for d in dev["devices"] if d['name'] == "DEVNAME") # Incorrect
False
>>> any(True for d in dev["devices"] if d['name'] == "DEVNAME") # Correct
True
Фактически, special_dict
объекты оцениваются как False, поэтому нет смысла проверять значение истинности d
в any()
. Использование True
работает, хотя.
PS : временные тесты показывают, что подход any(True … for … if … == …)
быстрее, чем хорошее any(… == … for …)
решение doublep:
python -m timeit -s "dev = {'devices': [{'name': 'BADNAME'} for _ in xrange(100)]}" "any(d['name'] == 'DEVNAME' for d in dev['devices'])"
100000 loops, best of 3: 16.3 usec per loop
python -m timeit -s "dev = {'devices': [{'name': 'BADNAME'} for _ in xrange(100)]}" "any(True for d in dev['devices'] if d['name'] == 'DEVNAME' )"
100000 loops, best of 3: 9.42 usec per loop
Причина в том, что второй генератор возвращает не более одного значения (True). Это можно увидеть, разобрав код Python для двух генераторов:
In [8]: def f(my_list):
...: return any(x == 11 for x in my_list)
In [12]: f.func_code.co_consts[1]
Out[12]: <code object <genexpr> at 0x1041f98b0, file "<ipython-input-8-384ce7986872>", line 2>
In [13]: dis.dis(_)
2 0 LOAD_FAST 0 (.0)
>> 3 FOR_ITER 17 (to 23)
6 STORE_FAST 1 (x)
9 LOAD_FAST 1 (x)
12 LOAD_CONST 0 (11)
15 COMPARE_OP 2 (==)
18 YIELD_VALUE
19 POP_TOP
20 JUMP_ABSOLUTE 3
>> 23 LOAD_CONST 1 (None)
26 RETURN_VALUE
Этот код содержит YIELD_VALUE
и POP_TOP
, которые занимают дополнительное время по сравнению с версией этого ответа:
In [14]: def g(my_list):
....: return any(True for x in my_list if x == 11)
In [15]: g.func_code.co_consts[1]
Out[15]: <code object <genexpr> at 0x1041f9630, file "<ipython-input-14-735c68947d80>", line 2>
In [16]: dis.dis(g.func_code.co_consts[1])
2 0 LOAD_FAST 0 (.0)
>> 3 FOR_ITER 23 (to 29)
6 STORE_FAST 1 (x)
9 LOAD_FAST 1 (x)
12 LOAD_CONST 0 (11)
15 COMPARE_OP 2 (==)
18 POP_JUMP_IF_FALSE 3
21 LOAD_GLOBAL 0 (True)
24 YIELD_VALUE
25 POP_TOP
26 JUMP_ABSOLUTE 3
>> 29 LOAD_CONST 1 (None)
32 RETURN_VALUE