Ошибка преобразования сложного кода в понимание списка - PullRequest
0 голосов
/ 08 января 2020

NB : Ни один из предложенных ответов не работает для меня, так как они предназначены для -l oop (что у меня уже работает) и не объясняют, что не так с версией для понимания списка.


Я пытаюсь преобразовать

('name:80', 'desc:100')

в

{'name': 80, 'desc': 100}

Работающий for -l oop:

new_wrap = {}
for item in wrap:
    k, v = item.split(':')
    new_wrap[k] = int(v)
wrap = new_wrap

нерабочий список-понимание:

wrap = dict([
    (k, int(v))
    for item in wrap
    for (k, v) in item.split(':')
    ])

, который дает

Traceback (most recent call last):
  File ..., line ..., in ...
    for (k, v) in item.split(':')
ValueError: too many values to unpack

Что я делаю не так?

Ответы [ 5 ]

11 голосов
/ 08 января 2020

Вы не хотите повторять над item.split(':'), вы хотите распаковать . Для этого вы можете ввести вложенное понимание или генераторное выражение. Это дает вам возможность создавать новые переменные k и v:

dict([
    (k, int(v))
    for k,v in (item.split(':') for item in wrap)
    ])

Я бы тогда избавился от квадратных скобок. Более эффективно использовать генераторное выражение, которое генерирует записи на лету, а не понимание списка, которое создает целый список в памяти, чтобы просто выбросить его при создании dict.

dict((k, int(v))
     for k,v in (item.split(':') for item in wrap))

Вы упрощаете его даже далее, используя сложное понимание с фигурными скобками:

{k: int(v) for k,v in (item.split(':') for item in wrap)}
5 голосов
/ 08 января 2020

Если вы хотите придерживаться понимания, которое имеет глубину в один уровень, и не возражаете против использования Python 3.8+, вы можете использовать выражение присваивания для хранения результата разделения в переменной для индексации:

{(t := s.split(':'))[0]: int(t[1]) for s in wrap}
1 голос
/ 08 января 2020

Вы должны отделить разбиение от преобразования в целое:

{k: int(v) for k, v in [w.split(":") for w in wrap]}
#{'name': 80, 'desc': 100}

Но, как правильно подсказал roganjo sh, вы ничего не получите от этого.

0 голосов
/ 15 января 2020

я нашел это решение:

x = ('name:80', 'desc:100') dict([tuple(a.split(':')) for a in x])

0 голосов
/ 13 января 2020

Благодаря пониманию, предоставленному Джоном Кугельманом, я смог выяснить проблему и решение, которое я хотел.


Рабочий код из for l oop:

k, v = item.split(':')

Разбивка:

  • item.split(':') == 'name:80'.split(':') == 'name', '80'
  • k, v = 'name', '80'
  • k == 'name' and v == 80

нерабочий код в list-comp:

for (k, v) in item.split(':')

Разбивка:

  • item.split(':') == 'name:80'.split(':') == 'name', '80'
  • for (k, v) in ('name', '80')

И есть проблема: in отличается от =. in перебирает свои аргументы, возвращая по одному за раз, поэтому:

  • k, v = 'n', 'a', 'm', 'e' - это то, что предпринимается, и поскольку четыре элемента пытаются объединить в два, мы получаем ValueError: too many values to unpack исключение.

Простое решение заключается в инкапсуляции item.split() в собственный набор:

  • for k, v in (item.split(':'), )

, который становится

  • for k, v in (('name', '80'), )

, и поскольку первый элемент в кортеже является кортежем, мы получаем

  • k, v = 'name', '80' для первого (и только) итерация второй for l oop

и проблема решена без вложения еще одной list-comp в первичную list-comp.

Финальную , работает list-comp:

    [
    (k, int(v))
    for item in wrap
    for (k, v) in (item.split(':'), )
    ]
...