Я немного озадачен следующим кодом:
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
print key, 'corresponds to', d[key]
То, что я не понимаю, это часть key
. Как Python распознает, что ему нужно только прочитать ключ из словаря? Является ли key
специальным словом в Python? Или это просто переменная?
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())
.
Это не тот ключ, это специальное слово, но словари реализуют протокол итератора. Вы можете сделать это в своем классе, например. см. этот вопрос о том, как создавать итераторы классов.
В словарях он реализован на уровне 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()
.
Итерация по 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)
Когда вы повторяете словари с помощью for .. in ..
-syntax, он всегда выполняет итерацию по клавишам (значения доступны с помощью dictionary[key]
).
Чтобы перебрать пары ключ-значение, используйте for k,v in s.iteritems()
.
items()
вместо iteritems()
Это очень распространенная идиома цикла. in
- оператор. Для использования for key in dict
и когда он должен быть for key in dict.keys()
см. статья Дэвида Гудгера Idiomatic Python.
in
, оператор часть , где вы проверить существование . Может быть, лучше удалить это in is an operator
информации in is an operator
.
Вы можете использовать это:
for key,val in d.items():
print key, 'is the key for ', val
У меня есть прецедент, когда я должен итерации через 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__
объекта (в данном случае словаря), который возвращает итератор (в данном случае объект-ключ):
>>> 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)
Но для академических целей пример вопроса просто замечательный.
Вы можете проверить реализацию dicttype
CPython на 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
, но вы были предупреждены;).
Диктонарии - это очень важный tpo Python, который также очень прост в использовании. Для повторения каждой клавиши словаря вы просто используете "для k в d" или "для ключа в d" или любую переменную вместо k или ключа, как в моих примерах. Это потому, что по умолчанию вы можете перебирать ключи словаря именно так. для доступа к значениям ключей, которые вы нам только выбрали d [k] или d [key] или d [nameofvariable], в зависимости от переменной, которую вы использовали в цикле, для итерации ключей.
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
print key, 'corresponds to', d[key]
вы также можете сделать что-то вроде этого:
d = {'x': 1, 'y': 2, 'z': 3}
for k,v in d.items():
print(k,":",v)
Выход
x : 1 y : 2 z : 3
sorted
.