Как вернуть ключи словаря в виде списка в Python?

785

В Python 2.7 я мог получить словарные ключи , значения или элементы в виде списка:

>>> newdict = {1:0, 2:0, 3:0}
>>> newdict.keys()
[1, 2, 3]

Теперь, в Python> = 3.3 , я получаю что-то вроде этого:

>>> newdict.keys()
dict_keys([1, 2, 3])

Итак, я должен сделать это, чтобы получить список:

newlist = list()
for i in newdict.keys():
    newlist.append(i)

Мне интересно, есть ли лучший способ вернуть список в Python 3 ?

Димитрис Фасаракис Хиллиард
источник
Интересная проблема безопасности темы по этой теме находится здесь: blog.labix.org/2008/06/27/…
Пол
2
Я новичок в Python, и мне кажется, что это распространение бесполезных новых типов данных является одним из худших аспектов Python. Какой смысл в этом типе dict_keys? Почему не список?
Фил Гетц

Ответы:

980

Попробуй list(newdict.keys()).

Это преобразует dict_keysобъект в список.

С другой стороны, вы должны спросить себя, имеет ли это значение. Pythonic способ кодирования состоит в том, чтобы предположить типизацию утки ( если это похоже на утку, и это крякает как утка, это - утка ). dict_keysОбъект будет действовать как список для большинства целей. Например:

for key in newdict.keys():
  print(key)

Очевидно, что операторы вставки могут не работать, но это не имеет особого смысла для списка словарных ключей в любом случае.

Крис
источник
49
newdict.keys () не поддерживает индексацию
gypaetus
57
list(newdict)также работает (по крайней мере, в Python 3.4). Есть ли причина использовать .keys()метод?
naught101
46
Примечание: в отладчике происходит pdb> list(newdict.keys()) сбой, потому что он конфликтует с командой pdb с тем же именем. Используйте pdb> !list(newdict.keys())для экранирования команд pdb.
Риаз Ризви
24
@ naught101 Да, .keys()гораздо яснее, что происходит.
Феликс Д.
2
Обратите внимание, что если вы используете list (newdict.keys ()), ключи не в том порядке, в котором вы их разместили из-за порядка хеширования!
Нейт М
278

Python> = 3.5 альтернатива: распаковать в список литерал [*newdict]

Новые обобщения распаковки (PEP 448) были введены в Python 3.5, что теперь позволяет легко выполнять:

>>> newdict = {1:0, 2:0, 3:0}
>>> [*newdict]
[1, 2, 3]

Распаковка *работает с любым итеративным объектом, и, поскольку словари возвращают свои ключи при повторении, вы можете легко создать список, используя его в литерале списка.

Добавление .keys()ie [*newdict.keys()]может помочь сделать ваши намерения немного более явными, хотя это будет стоить вам поиск и вызов функции. (что, честно говоря, это не то, что вы должны действительно беспокоиться).

*iterableСинтаксис аналогичен делать list(iterable)и его поведение было изначально зафиксировано в разделе Вызовы на Python Справочное руководство. С PEP 448 *iterableбыло ослаблено ограничение на место появления, что позволило также размещать его в литералах списков, наборов и кортежей. Справочное руководство по спискам выражений также было обновлено.


Хотя это эквивалентно list(newdict)тому, что это быстрее (по крайней мере, для небольших словарей), потому что на самом деле не выполняется вызов функции:

%timeit [*newdict]
1000000 loops, best of 3: 249 ns per loop

%timeit list(newdict)
1000000 loops, best of 3: 508 ns per loop

%timeit [k for k in newdict]
1000000 loops, best of 3: 574 ns per loop

с большими словарями скорость практически одинакова (накладные расходы на итерацию большой коллекции превышают небольшие затраты на вызов функции).


Аналогичным образом вы можете создавать кортежи и наборы словарных ключей:

>>> *newdict,
(1, 2, 3)
>>> {*newdict}
{1, 2, 3}

остерегайтесь запятой в случае кортежа!

Димитрис Фасаракис Хиллиард
источник
великое объяснение, но , пожалуйста , вы можете обратиться на любую ссылку , которая описывает этот тип «*» newdict синтаксиса, я имею в виду , как и почему это возвращает ключи от словаря только для understanding.Thanx
Мухаммад Юнус
1
@MYounas Этот синтаксис был доступен в течение достаточно долгого времени, даже в Python 2. В вызовах функций вы можете выполнять с def foo(*args): print(args)последующим выводом foo(*{1:0, 2:0})результата (1, 2). Это поведение указано в разделе « Вызовы » справочного руководства. Python 3.5 с PEP 448 просто ослабил ограничения на то, где они могут появиться, [*{1:0, 2:0}]и теперь их можно использовать. В любом случае, я отредактирую свой ответ и включу их.
Димитрис Фасаракис Хиллиард
1
*newdict- это определенно ответ для игроков в гольф кода; P. Кроме того: что, честно говоря, это не то, что вы действительно должны беспокоиться - и если вы, не используйте Python .
Артемида до сих пор не доверяет SE
46

list(newdict)работает как в Python 2, так и в Python 3, предоставляя простой список ключей в newdict. keys()не обязательно (:

Себ
источник
26

Немного оторвано от определения «типизирования утки» - dict.keys()возвращает итеративный объект, а не объект, подобный списку. Он будет работать везде, где будет работать итерация, а не в любом месте списка. список также является итеративным, но итеративный НЕ является списком (или последовательностью ...)

В реальных случаях использования наиболее распространенные действия с ключами в dict - это их итерация, так что это имеет смысл. И если они вам нужны как список, вы можете позвонить list().

Точно так же zip()- в подавляющем большинстве случаев он повторяется - зачем создавать целый новый список кортежей, просто повторять его, а затем выбрасывать снова?

Это часть большой тенденции в Python использовать больше итераторов (и генераторов), а не копировать списки повсюду.

dict.keys() должен работать с пониманием, хотя - проверьте внимательно на опечатки или что-то ... это прекрасно работает для меня:

>>> d = dict(zip(['Sounder V Depth, F', 'Vessel Latitude, Degrees-Minutes'], [None, None]))
>>> [key.split(", ") for key in d.keys()]
[['Sounder V Depth', 'F'], ['Vessel Latitude', 'Degrees-Minutes']]
Крис Баркер
источник
2
Вам даже не нужно использовать .keys(); объект словаря является сам итерацию и производит ключи при итерации: [key.split(", ") for key in d].
Мартин Питерс
25

Вы также можете использовать понимание списка :

>>> newdict = {1:0, 2:0, 3:0}
>>> [k  for  k in  newdict.keys()]
[1, 2, 3]

Или короче,

>>> [k  for  k in  newdict]
[1, 2, 3]

Примечание: заказ не гарантируется в версиях под 3.7 (заказ по-прежнему только деталь реализации с CPython 3.6).

未来 陆家嘴 顶尖 的 投资 人
источник
6
Просто используйте list(newdict). Здесь нет необходимости для понимания списка.
Мартин Питерс
8

Преобразование в список без использования keysметода делает его более читабельным:

list(newdict)

и при просмотре словарей нет необходимости keys():

for key in newdict:
    print key

если вы не изменяете его в цикле, для которого потребуется предварительно созданный список ключей:

for key in list(newdict):
    del newdict[key]

На Python 2 наблюдается незначительный прирост производительности при использованииkeys() .

Cas
источник
8

Если вам нужно хранить ключи отдельно, вот решение, которое требует меньше ввода, чем любое другое решение, представленное до сих пор, с использованием расширенной итерируемой распаковки (python3.x +).

newdict = {1: 0, 2: 0, 3: 0}
*k, = newdict

k
# [1, 2, 3]

            ╒═══════════════╤═════════════════════════════════════════╕
             k = list(d)      9 characters (excluding whitespace)   
            ├───────────────┼─────────────────────────────────────────┤
             k = [*d]         6 characters                          
            ├───────────────┼─────────────────────────────────────────┤
             *k, = d          5 characters                          
            ╘═══════════════╧═════════════════════════════════════════╛
cs95
источник
1
Единственное небольшое замечание, которое я хотел бы отметить, это то, что kздесь всегда есть список. Если пользователь хочет получить кортеж или набор из ключей, ему необходимо обратиться к другим параметрам.
Димитрис Фасаракис Хиллиард
1
Более примечательным примечанием является тот факт, что, как утверждение, *k, = dимеет ограничения на то, где он может появиться (но посмотрите и, возможно, обновите этот ответ для PEP 572 - расширенная распаковка не поддерживается для выражений присваивания atm, но это может произойти когда-нибудь! )
Димитрис Фасаракис Хиллиард
Что делать, если вы хотите, чтобы ключи и значения в списках?
эндолиты
1
@endolith возможно keys, vals = zip(*d.items())(хотя это дает два кортежа, достаточно близко). Я не знаю более короткого выражения, чем это.
cs95
1

Я могу придумать 2 способа, которыми мы можем извлечь ключи из словаря.

Способ 1: - Чтобы получить ключи с помощью метода .keys (), а затем преобразовать его в список.

some_dict = {1: 'one', 2: 'two', 3: 'three'}
list_of_keys = list(some_dict.keys())
print(list_of_keys)
-->[1,2,3]

Способ 2: - Создать пустой список, а затем добавить ключи к списку через цикл. Вы также можете получить значения с помощью этого цикла (используйте .keys () только для ключей и .items () для извлечения ключей и значений)

list_of_keys = []
list_of_values = []
for key,val in some_dict.items():
    list_of_keys.append(key)
    list_of_values.append(val)

print(list_of_keys)
-->[1,2,3]

print(list_of_values)
-->['one','two','three']
Рахул
источник