Я немного озадачен следующим кодом:
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
print key, 'corresponds to', d[key]
Чего я не понимаю, так это части key
. Как Python распознает, что ему нужно только прочитать ключ из словаря? key
- это особое слово в Python? Или это просто переменная?
10 ответов
key
это просто имя переменной.
for key in d:
Просто перебирает ключи в словаре, а не ключи и значения. Чтобы перебрать как ключ, так и значение, вы можете использовать следующее:
Для Python 3.x:
for key, value in d.items():
Для Python 2.x:
for key, value in d.iteritems():
Чтобы проверить себя, измените слово 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())
.
Итерации по 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
в качестве имен переменных при зацикливании на 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))
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)
Это очень распространенная идиома. in
является оператором. О том, когда использовать for key in dict
и когда это должно быть for key in dict.keys()
, см. Статья Дэвида Гуджера об идиоматическом Python (архивная копия) .
У меня есть сценарий использования, когда мне нужно пройти через dict, чтобы получить ключ, пару значений, а также индекс, указывающий, где я нахожусь. Вот как я это делаю:
d = {'x': 1, 'y': 2, 'z': 3}
for i, (key, value) in enumerate(d.items()):
print(i, key, value)
Обратите внимание, что круглые скобки вокруг ключа, значения важны, без скобок вы получаете ValueError «недостаточно значений для распаковки».
Перебор словарей с использованием циклов 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)
Но для академических целей пример вопроса просто отлично.
Для итерации по ключам медленнее, но лучше использовать my_dict.keys()
. Если вы пытались сделать что-то вроде этого:
for key in my_dict:
my_dict[key+"-1"] = my_dict[key]-1
Это приведет к ошибке во время выполнения, потому что вы меняете ключи во время работы программы. Если вы абсолютно настроены на сокращение времени, используйте способ for key in my_dict
, но вы были предупреждены;).
Вы можете проверить реализацию dicttype
CPython на GitHub. Это сигнатура метода, который реализует итератор dict:
_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
PyObject **pvalue, Py_hash_t *phash)
Когда вы перебираете словари, используя синтаксис for .. in ..
, он всегда перебирает ключи (значения доступны с помощью dictionary[key]
).
Для итерации по парам ключ-значение в Python 2 используйте for k,v in s.iteritems()
, а в Python 3 for k,v in s.items()
.
Дело не в том, что ключ - это особое слово, а в том, что словари реализуют протокол итератора. Вы можете сделать это в своем классе, например, см. этот вопрос, чтобы узнать, как создавать итераторы классов.
В случае словарей это реализовано на уровне C. Подробности доступны в PEP 234. В частности, раздел под названием «Словарь итераторов»:
Словари реализуют слот tp_iter, который возвращает эффективный итератор, который перебирает ключи словаря. [...] Эта означает, что мы можем написать
для k в dict: ... Код >
что эквивалентно, но намного быстрее чем
для k в dict.keys (): ... Код >
до тех пор, пока ограничение на изменения в словаре (либо циклом, либо другим потоком) не нарушаются.
Добавьте методы в словари, которые возвращают различные виды итераторы явно:
для ключа в dict.iterkeys (): ... для значения в dict.itervalues (): ... для ключа значение в dict.iteritems (): ... Код >
Это означает, что
for x in dict
является сокращением длядля x в dict.iterkeys ( ) код > . р >
В Python 3 dict.iterkeys()
, dict.itervalues()
и dict.iteritems()
больше не поддерживаются. Вместо этого используйте dict.keys()
, dict.values()
и dict.items()
.
Похожие вопросы
Связанные вопросы
Новые вопросы
python
Python — это мультипарадигмальный многоцелевой язык программирования с динамической типизацией. Он предназначен для быстрого изучения, понимания и использования, а также обеспечивает чистый и унифицированный синтаксис. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Если у вас есть вопросы о версии Python, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas, NumPy) укажите это в тегах.