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

python python-2.7 dictionary

3956235 просмотра

10 ответа

14676 Репутация автора

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

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

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

Автор: TopChef Источник Размещён: 20.07.2010 10:27

Ответы (10)


51 плюса

39643 Репутация автора

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

Для перебора пар ключ-значение в Python 2 for k,v in s.iteritems()и в Python 3 for k,v in s.items().

Автор: Alexander Gessler Размещён: 20.07.2010 10:29

4885 плюса

95827 Репутация автора

Решение

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 Размещён: 20.07.2010 10:29

27 плюса

6208 Репутация автора

Это очень распространенная идиома. inэто оператор. О том, когда for key in dictи когда его использовать, можно прочитать в for key in dict.keys()статье «Идиоматический Python» Дэвида Гуджера (архивная копия) .

Автор: chryss Размещён: 20.07.2010 10:42

72 плюса

2421 Репутация автора

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 Размещён: 20.07.2010 11:49

394 плюса

87787 Репутация автора

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

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

Автор: ars Размещён: 20.07.2010 11:52

187 плюса

222363 Репутация автора

Итерация по 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)]

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

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

Использование kи в vкачестве имен переменных при зацикливании над a 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 Размещён: 21.07.2010 01:27

2 плюса

160 Репутация автора

Перебирать ключи медленнее, но лучше использовать 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 Размещён: 31.12.2015 06:39

14 плюса

5567 Репутация автора

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

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

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

Автор: jdhao Размещён: 25.05.2017 01:42

12 плюса

199253 Репутация автора

Перебор словарей с использованием циклов 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

Если мы хотим перебрать значения, нам нужно использовать .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 Размещён: 21.06.2017 02:51

7 плюса

9233 Репутация автора

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

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

CPython dictobject.c

Автор: abc Размещён: 03.11.2017 05:16
Вопросы из категории :
32x32