Итерация над словарями с использованием циклов 'for'

Я немного озадачен следующим кодом:

 d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    print key, 'corresponds to', d[key]
 

То, что я не понимаю, это key часть. Как Python распознает, что ему нужно только прочитать ключ из словаря? Является ли key специальным словом в Python? Или это просто переменная?

вопрос задан 20.07.2010
TopChef
11816 репутация

11 ответов


  • 3975 рейтинг

    key - просто имя переменной.

     for key in d:
     

    будет просто перебирать ключи в словаре, а не ключи и значения. Чтобы перебрать оба ключа и значения, вы можете использовать следующее:

    Для Python 2.x:

     for key, value in d.iteritems():
     

    Для Python 3.x:

     for key, value in d.items():
     

    Чтобы проверить себя, измените слово key на poop .

    Для Python 3.x, iteritems() было заменено просто на items() , что возвращает представление типа, поддерживаемое dict, например iteritems() но еще лучше. Это также доступно в 2.7 как viewitems() .

    Операция items() будет работать как для 2, так и для 3, но в 2 она вернет список (key, value) пар слов словаря, которые не будут отражать изменения в dict, которые произойдут после items() вызова. Если вы хотите 2.x поведение в 3.x, вы можете позвонить list(d.items()) .

    ответ дан sberry, с репутацией 83178, 20.07.2010
  • 333 рейтинг

    Это не тот ключ, это специальное слово, но словари реализуют протокол итератора. Вы можете сделать это в своем классе, например, см. Этот вопрос о том, как создавать итераторы классов.

    В словарях он реализован на уровне C. Подробности доступны в PEP 234 . В частности, раздел «Итераторы словарей»:

    • Словари реализуют слот tp_iter, который возвращает эффективный итератор, который выполняет итерацию по клавишам словаря. [...] Это означает, что мы можем написать

       for k in dict: ...
       

      что эквивалентно, но намного быстрее, чем

       for k in dict.keys(): ...
       

      пока ограничение на модификации словаря (ни по циклу, ни по другому потоку) не будет нарушено.

    • Добавьте методы в словари, которые явным образом возвращают разные типы итераторов:

       for key in dict.iterkeys(): ...
      
      for value in dict.itervalues(): ...
      
      for key, value in dict.iteritems(): ...
       

      Это означает, что for x in dict является сокращением на for x in dict.iterkeys() .

    ответ дан ars, с репутацией 79125, 20.07.2010
  • 157 рейтинг

    Итерируя через dict итерации через его ключи не имеют особого порядка, как вы можете видеть здесь:

    Edit: (Это уже не так в Python3.6 , но обратите внимание, что это еще не гарантированное поведение)

     >>> d = {'x': 1, 'y': 2, 'z': 3} 
    >>> list(d)
    ['y', 'x', 'z']
    >>> d.keys()
    ['y', 'x', 'z']
     

    Для вашего примера лучше использовать dict.items() :

     >>> d.items()
    [('y', 2), ('x', 1), ('z', 3)]
     

    Это дает вам список кортежей. Когда вы перебираете их так, каждый кортеж автоматически распаковывается в k и v :

     for k,v in d.items():
        print(k, 'corresponds to', v)
     

    Использование k и v качестве имен переменных, когда цикл через dict довольно распространен, если тело цикла - всего несколько строк. Для более сложных циклов может быть хорошей идеей использовать более описательные имена:

     for letter, number in d.items():
        print(letter, 'corresponds to', number)
     

    Это хорошая идея, чтобы привыкнуть использовать строки форматирования:

     for letter, number in d.items():
        print('{0} corresponds to {1}'.format(letter, number))
     
    ответ дан John La Rooy, с репутацией 201824, 21.07.2010
  • 53 рейтинг

    key - просто переменная.

    Для Python2.X :

     d = {'x': 1, 'y': 2, 'z': 3} 
    for my_var in d:
        print my_var, 'corresponds to', d[my_var]
     

    ... или лучше,

     d = {'x': 1, 'y': 2, 'z': 3} 
    for the_key, the_value in d.iteritems():
        print the_key, 'corresponds to', the_value
     

    Для Python3.X :

     d = {'x': 1, 'y': 2, 'z': 3} 
    for the_key, the_value in d.items():
        print(the_key, 'corresponds to', the_value)
     
    ответ дан ssoler, с репутацией 2003, 20.07.2010
  • 40 рейтинг

    Когда вы перебираете словари с использованием for .. in .. синтаксиса, он всегда выполняет итерацию по клавишам (значения доступны с помощью dictionary[key] ).

    Чтобы перебрать пары ключ-значение, используйте for k,v in s.iteritems() .

    ответ дан Alexander Gessler, с репутацией 38174, 20.07.2010
  • 20 рейтинг

    Это очень распространенная идиотская петля. in - оператор. Для того, чтобы использовать for key in dict и когда это должно быть for key in dict.keys() см. Статью Идиоматического Питона Дэвида Гудгера .

    ответ дан chryss, с репутацией 5887, 20.07.2010
  • 9 рейтинг

    Вы можете использовать это:

     for key,val in d.items():
        print key, 'is the key for ', val
     
    ответ дан A H M Forhadul Islam, с репутацией 802, 14.01.2017
  • 7 рейтинг

    У меня есть прецедент, где я должен итерации через dict, чтобы получить ключ, пара значений, а также индекс, указывающий, где я. Вот как я это делаю:

     d = {'x': 1, 'y': 2, 'z': 3} 
    for i, (key, value) in enumerate(d.items()):
       print(i, key, value)
     

    Обратите внимание, что круглые скобки вокруг ключа, значение важно, без круглых скобок вы получаете значение ValueError «Недостаточно значений для распаковки».

    ответ дан jdhao, с репутацией 2966, 25.05.2017
  • 5 рейтинг

    Итерация над словарями с использованием циклов 'for'

     d = {'x': 1, 'y': 2, 'z': 3} 
    for key in d:
        ...
     

    Как Python распознает, что ему нужно только прочитать ключ из словаря? Является ли ключевым слово в Python? Или это просто переменная?

    Это не только for цикл. Важным словом здесь является «итерация».

    Словарь - это отображение ключей к значениям:

     d = {'x': 1, 'y': 2, 'z': 3} 
     

    Каждый раз, когда мы перебираем его, мы перебираем ключи. Имя переменной key предназначено только для описания, и оно вполне подходит для этой цели.

    Это происходит в понимании списка:

     >>> [k for k in d]
    ['x', 'y', 'z']
     

    Это происходит, когда мы передаем словарь для отображения (или любого другого объекта типа коллекции):

     >>> list(d)
    ['x', 'y', 'z']
     

    То, как выполняется итерация Python, в контексте, где это необходимо, вызывает метод __iter__ объекта (в данном случае словарь), который возвращает итератор (в данном случае объект-ключ):

     >>> d.__iter__()
    <dict_keyiterator object at 0x7fb1747bee08>
     

    Мы не должны использовать эти специальные методы самостоятельно, вместо этого используем соответствующую встроенную функцию для ее вызова, iter :

     >>> key_iterator = iter(d)
    >>> key_iterator
    <dict_keyiterator object at 0x7fb172fa9188>
     

    Итераторы имеют метод __next__ но мы называем его встроенной функцией, next :

     >>> next(key_iterator)
    'x'
    >>> next(key_iterator)
    'y'
    >>> next(key_iterator)
    'z'
    >>> next(key_iterator)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
     

    Когда итератор исчерпан, он поднимает StopIteration . Это то, как Python знает, как выйти из цикла for , или понимания списка, или выражения генератора, или любого другого итеративного контекста. Как только итератор поднимает StopIteration он всегда будет поднимать его - если вы хотите снова итерации, вам нужен новый.

     >>> list(key_iterator)
    []
    >>> new_key_iterator = iter(d)
    >>> list(new_key_iterator)
    ['x', 'y', 'z']
     

    Возвращение в диктофоны

    Мы видели, как во многих контекстах повторяется итерация. То, что мы видели, это то, что в любой момент, когда мы перебираем диктофон, мы получаем ключи. Вернемся к исходному примеру:

     d = {'x': 1, 'y': 2, 'z': 3} 
    for key in d:
     

    Если мы изменим имя переменной, мы все равно получим ключи. Давай попробуем:

     >>> for each_key in d:
    ...     print(each_key, '=>', d[each_key])
    ... 
    x => 1
    y => 2
    z => 3
     

    Если мы хотим перебирать значения, нам нужно использовать .values метод dicts или для обоих вместе .items :

     >>> list(d.values())
    [1, 2, 3]
    >>> list(d.items())
    [('x', 1), ('y', 2), ('z', 3)]
     

    В приведенном примере было бы более эффективно выполнять итерацию по таким элементам:

     for a_key, corresponding_value in d.items():
        print(a_key, corresponding_value)
     

    Но в академических целях пример вопроса в порядке.

    ответ дан Aaron Hall, с репутацией 153756, 21.06.2017
  • 3 рейтинг

    Вы можете проверить реализацию CPython's dicttype на GitHub. Это подпись метода, который реализует итератор dict:

     _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
                 PyObject **pvalue, Py_hash_t *phash)
     

    CPython dictobject.c

    ответ дан abc, с репутацией 8101, 3.11.2017
  • 0 рейтинг

    Для итерации по клавишам она медленнее, но лучше использовать my_dict.keys() . Если вы попытались сделать что-то вроде этого:

     for key in my_dict:
        my_dict[key+"-1"] = my_dict[key]-1
     

    это создаст ошибку времени выполнения, потому что вы меняете ключи во время работы программы. Если вы полностью настроены на сокращение времени, используйте for key in my_dict способа, но вы были предупреждены;).

    ответ дан Neil Chowdhury o_O, с репутацией 120, 31.12.2015