Итерация по словарям с использованием циклов' for'
Я немного озадачен следующим кодом:
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
print key, 'corresponds to', d[key]
чего я не понимаю-это key часть. Как Python распознает, что ему нужно только прочитать ключ из словаря? Это key специальное слово в Python? Или это просто переменная?
11 ответов:
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(), который возвращает set-like вид при поддержке диктатора, какiteritems()но даже лучше. Это также доступно в 2.7 какviewitems().операция
items()будет работать как для 2, так и для 3, но в 2 он вернет список словаря(key, value)пары, которые не будут отражать изменения в dict, которые происходят послеitems()звонок. Если вы хотите 2.X поведение в 3.х, вы можете позвонитьlist(d.items()).
дело не в том, что ключ-это специальное слово, а в том, что словари реализуют протокол итератора. Вы можете сделать это в своем классе, например, см. этот вопрос как построить итераторы класса.
в случае словарей, это реализовано на уровне C. Подробности доступны в PEP 234. В частности, раздел под названием "словарные итераторы":
словари реализуют слот tp_iter, который возвращает эффективный iterator, который выполняет итерации по ключам словаря. [...] Этот значит, мы можем написать
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().
итерация по a
dictперебирает свои ключи в произвольном порядке, как вы можете увидеть здесь:Edit: (это не в Питон3.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)
при итерации по словарям с помощью
for .. in ..-синтаксис, он всегда перебирает ключи (значения можно с помощьюdictionary[key]).для перебора пар ключ-значение, используйте
for k,v in s.iteritems().
Это очень распространенная идиома цикла.
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 распознает, что ему нужно только прочитать ключ из словарь? Является ли key специальным словом в 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метод диктов, или для обоих вместе,.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)но для академических целей, пример вопроса-просто отлично.
Вы можете проверить реализацию с CPython это
dicttypeна GitHub. Это сигнатура метода, реализующего итератор dict:_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue, Py_hash_t *phash)
чтобы перебирать ключи, это медленнее, но лучше использовать
my_dict.keys(). Если вы попытались сделать что-то вроде этого:for key in my_dict: my_dict[key+"-1"] = my_dict[key]-1это создаст ошибку времени выполнения, потому что вы меняете ключи во время работы программы. Если вы абсолютно настроены на сокращение времени, используйте
for key in my_dictпуть, но вы были предупреждены ;).
Comments