2015-02-27 1 views
0

Я пока не тестировал сравнение, и мне интересно узнать стоимость метода items() (или keys() или values ​​()) словаря в пределах итерации. Поясню:Python dictionnary items() метод cost in iterable

У меня 2 dictionnaries (конечно, мои настоящие dicts гораздо больше):

One = {'a': 'dontmind', 'b': 'dontmind', 'c': 'whatever'} 
Two = {'a': 'dontmind', 'c': 'dontmind'} 

Я хочу, чтобы проверить, если все ключи «Два» находятся в «One» и будет делать это нравится:

if all([key in One.keys() for key in Two.keys()]) : 
    # do stuff! 

Я хочу знать, если этот путь лучше, учитывая производительность:

one_keys = One.keys() 
two_keys = Two.keys() 
if all([key in one_keys for key in two_keys]) : 
    # do stuff! 

в этом case, метод keys() вызывается только один раз для каждого dict. Я действительно не знаю о базовом процессе извлечения ключей из dict, и является ли разница между этими двумя способами действительно значимой. Вы можете мне помочь?

Кроме того, следует ли мне так подумать?

one_keys = One.keys() 
two_keys = Two.keys() 
for key in two_keys : 
    if key not in one_keys : 
    break 
else : 
    # do stuff! 

Благодарим за ответы.

+0

Какую версию Python вы используете? –

+1

Я использую python 2.7 –

ответ

2

Если Python 2.x, .keys() возвращает список, поэтому вызов, что несколько раз это немного накладные расходы ... В 3.x, он возвращает dict_keys объект, который имеет set -как поведение, таким образом, Простейшим для 3.x будет:

contains_all = two.keys() <= one.keys() 

эквивалент в Python 2.7 viewkeys:

contains_all = two.viewkeys() <= one.viewkeys() 

для более ранних версий, конвертировать two в установившие d проверить это подмножество one, например:

contains_all = set(two).issubset(one) 

Python 3.x тайминги:

%timeit two.keys() <= one.keys() 
# 1000000 loops, best of 3: 557 ns per loop 
%timeit set(two).issubset(one) 
# 1000000 loops, best of 3: 732 ns per loop 
%timeit all(key in one for key in two) 
# 1000000 loops, best of 3: 1.24 µs per loop 

Python 2.7 таймингов (показать .viewkeys()):

%timeit two.viewkeys() <= one.viewkeys() 
# 1000000 loops, best of 3: 484 ns per loop 
%timeit set(two).issubset(one) 
# 1000000 loops, best of 3: 677 ns per loop 
%timeit all(key in one for key in two) 
# 1000000 loops, best of 3: 1.37 µs per loop 
+0

Is '<=' оператор в списке, чтобы проверить, все ли элементы одного находятся в другом? Или это сравнение длины? (может быть, глупый вопрос) –

+0

'<=' в этом случае работает на 'set'-подобных объектах (' dict_keys'), и это эквивалентно 'set.issubset' - который проверяет, что все клавиши, присутствующие слева, присутствуют на right –

+0

Хорошо, я получил это, большое спасибо –

1

Для лучшей производительности в обоих 2.7 (но не более ранних версий) и 3.x, я рекомендовал бы писать это:

if all(key in One for key in Two): 
    # do stuff! 

Это позволяет избежать нескольких ошибок:

  • Генератор выражения не вытащить всю последовательность в память, понимают способы отображения списка.
  • В 2.x, .keys() возвращает список. Тестирование членства в списке происходит медленно, но тестирование членства в словаре происходит быстро. В 3.x, .keys() возвращает объект, подобный множеству, так что это не проблема.
  • Кроме того, этот список занимает дополнительное пространство, которое мы сохраняем под 2,7. 3.x's set-like .keys() - это «вид» существующего словаря, поэтому снова это не проблема под 3.x.
+0

Спасибо за этот быстрый ответ! Я попробую это. Я планирую сделать некоторые бенчмаркинга, я сообщу об этом, если вы захотите. –

+1

@ jean.stache: Помните, что когда мы говорим о скорости, мы обычно фокусируемся на * масштабируемости *, а не на абсолютном времени. Словарь «быстрее», чем два списка с соответствующими индексами, потому что словарь может разумно масштабироваться до сотен или тысяч записей, в то время как списки становятся слишком медленными, поскольку они становятся большими. Если вы тестируете небольшие примеры, вы можете не видеть большой разницы или даже получить противоположные результаты. – Kevin

+0

Спасибо за этот совет Kevin –

 Смежные вопросы

  • Нет связанных вопросов^_^