it-swarm.com.ru

Перебор словарей с использованием циклов for

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

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

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

2719
TopChef

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()).

4804
sberry

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

В случае словарей это реализовано на уровне 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().

В Python 3 dict.iterkeys(), dict.itervalues() и dict.iteritems() больше не поддерживаются. Вместо этого используйте dict.keys(), dict.values() и dict.items().

387
ars

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

Правка: (Это больше не имеет место в 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)]

Это дает вам список кортежей. Когда вы перебираете их так, каждый Tuple автоматически распаковывается в 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))
183
John La Rooy

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)
72
ssoler

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

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

50
Alexander Gessler

Это очень распространенная идиома. in является оператором. Информацию о том, когда использовать for key in dict и когда это должно быть for key in dict.keys(), см. В статье David Igermatic Idiomatic Python (архивная копия) .

26
chryss

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

for key,val in d.items():
    print key, 'is the key for ', val
16
A H M Forhadul Islam

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

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

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

13
jdhao

как бы то ни было, сегодня python 2.6 и 2.7, а также 3.x в моем окне хорошо работают с items():

z = {0: 'a', 1: 'b'}
for k, v in z.items(): print(v, k)
12
象嘉道

Перебор словарей с использованием циклов 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__ объекта (в данном случае словарь), который возвращает итератор (в данном случае объект keyiterator):

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

Если мы хотим перебрать значения, нам нужно использовать метод dicts .values или для обоих вместе, .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)

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

12
Aaron Hall

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

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

CPython dictobject.c

7
abc

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

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

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

2
Neil Chowdhury o_O

Для ключа в my_dict фактически равно для ключа в my_dict.keys (). Поэтому, если вы хотите получить значения dict, вы можете попробовать два метода.

Один:

for value in my_dict.values():
    print(value)

Два:

for key in my_dict:
    print(my_dict[key])
1
Amaan Durrani

Распечатка предложения для длинных значений
Если у вас есть длинные строки в значениях, вот быстрый способ распечатать это в (более?) Читаемом формате:
for key, value in my_dictionary.iteritems(): print(key) print("---------") print(value) print("\n")

0
Joseph True