python用法 - python辭典




使用'for'循環迭代字典 (8)

我對以下代碼感到有點困惑:

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

我不明白的是key部分。 Python如何識別它只需要從字典中讀取密鑰? key是Python中的一個特殊詞嗎? 或者它只是一個變量?


使用'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']

回到dicts

我們已經看到dicts在許多情況下迭代。 我們所看到的是,無論何時我們迭代dict,我們都會得到密鑰。 回到原始示例:

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)

但是出於學術目的,問題的例子很好。


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)

並不是密鑰是一個特殊的單詞,而是字典實現了迭代器協議。 您可以在您的類中執行此操作,例如,請參閱此問題以了解如何構建類迭代器。

在字典的情況下,它是在C級實現的。 有關詳細信息,請參閱PEP 234 。 特別是標題為“Dictionary Iterators”的部分:

  • 字典實現了一個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 dictfor x in dict.iterkeys()


你可以用這個:

for key,val in d.items():
    print key, 'is the key for ', val

您可以在GitHub上檢查CPython的dicttype的實現。 這是實現dict迭代器的方法的簽名:

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

CPython dictobject.c


我有一個用例,我必須遍歷dict以獲取鍵,值對,以及指示我在哪裡的索引。 我是這樣做的:

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

請注意,鍵周圍的括號值很重要,如果沒有括號,則會得到ValueError“沒有足夠的值來解包”。


要迭代鍵,使用my_dict.keys()會更慢但更好。 如果您嘗試執行以下操作:

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

它會產生運行時錯誤,因為您在程序運行時更改了鍵。 如果您絕對準備減少時間,請for key in my_dict方式使用for key in my_dict ,但您已收到警告;)。


這是一個非常常見的循環習語。 in是一個運營商。 關於何時使用for key in dict以及何時必須使用for key in dict.keys()請參閱David Goodger的Idiomatic Python文章





dictionary