Чому вам потрібно викликати .items () під час ітерації над словником на Python?


131

Чому вам потрібно зателефонувати items()на повторення через ключ, значення пар у словнику? тобто.

dic = {'one': '1', 'two': '2'}
for k, v in dic.items():
    print(k, v)

Чому це не поведінка за замовчуванням ітерації над словником

for k, v in dic:
    print(k, v)

Відповіді:


171

Для кожного контейнера python C очікування таке

for item in C:
    assert item in C

пройде нормально - НЕ ви знайдете це дивно , якщо один сенс in(клаузули циклу) мав зовсім інше значення від інших (перевірок присутності)? Я впевнений, що! Це, природно, працює таким чином для списків, наборів, кортежів, ...

Отже, коли Cє словник, якби inотримувати ключі / значення ключів у forциклі, тоді, за принципом найменшого здивування, inтакож слід було б взяти такий кортеж, як його лівий операнд у контрольній стрибці.

Наскільки це було б корисно? Досить даремний дійсно, в основному робить if (key, value) in Cсинонім if C.get(key) == value- що перевірка Я вважаю , що , можливо, виконані, або хотів виконати, в 100 разів рідше , ніж те , що на if k in Cсамому ділі означає , перевірка наявності ключа тільки і повністю ігноруючи значення.

З іншого боку, бажання циклічити лише на клавішах є досить поширеним, наприклад:

for k in thedict:
    thedict[k] += 1

а також цінність не допоможе особливо:

for k, v in thedict.items():
    thedict[k] = v + 1

насправді дещо менш чіткий і менш стислий. (Зауважте, що itemsоригінальне написання "належних" методів було використано для отримання пар ключів / значень: на жаль, це було ще в часи, коли такі користувачі повертали цілі списки, тому для підтримки "просто повторення" альтернативне написання довелося запровадити , і iteritems це було - в Python 3, де обмеження сумісності назад із попередніми версіями Python були значно послаблені, воно itemsзнову стало ).


10

Я здогадуюсь: використання повного кортежу було б більш інтуїтивно зрозумілим, але, можливо, менше для тестування на використання членства in.

if key in counts:
    counts[key] += 1
else:
    counts[key] = 1

Цей код насправді не спрацював, якби вам довелося вказати і ключ, і значення для in. Мені важко уявити випадок використання, коли ви перевірите, чи в словнику є обидва значення ключа І значення. Набагато природніше лише тестувати клавіші.

# When would you ever write a condition like this?
if (key, value) in dict:

Тепер не обов’язково, щоб inоператор і for ... inпрацював над одними і тими ж елементами. Це стосується різних операцій ( __contains__порівняно __iter__). Але ця маленька неузгодженість була б дещо заплутаною і, ну, непослідовною.


Зважаючи на те, що для будь-якого іншого типу побудованого ітерабельного, про який я можу придумати, x in fooлише якщо iв певному моменті for i in fooприпускається значення x, я б сказав, що це було б дуже величезною невідповідністю.
aaronasterling
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.