Распаковка Python - кортеж в понимании dict
Я пытаюсь написать функцию, которая превращает строки формы 'A=5, b=7'
в dict {'A': 5, 'b': 7}
. Следующие фрагменты кода происходят внутри основного цикла for
- они превращают одну часть строки в один элемент dict.
Это нормально:
s = 'A=5'
name, value = s.split('=')
d = {name: int(value)}
Это не:
s = 'A=5'
d = {name: int(value) for name, value in s.split('=')}
ValueError: need more than 1 value to unpack
Почему я не могу распаковать кортеж, когда он в понимании dict? Если я получу эту работу, я могу легко превратить всю функцию в одно компактное понимание.
Ответы
Ответ 1
В вашем коде s.split('=')
вернет список: ['A', '5']
. При повторении этого списка одна строка возвращается каждый раз (первый раз это 'A'
, второй раз это '5'
), поэтому вы не можете распаковать эту одиночную строку на 2 переменные.
Вы можете попробовать: for name,value in [s.split('=')]
Скорее всего, у вас есть итерабельность строк, которые вы хотите разделить, - тогда ваше понимание понятий становится простым (2 строки):
splitstrs = (s.split('=') for s in list_of_strings)
d = {name: int(value) for name,value in splitstrs }
Конечно, если вы одержимы 1-лайнером, вы можете комбинировать его, но я бы этого не сделал.
Ответ 2
Некоторые люди склонны полагать, что вы отправитесь в ад для использования eval
, но...
s = 'A=5, b=7'
eval('dict(%s)' % s)
Или лучше, чтобы быть в безопасности (спасибо mgilson за указание):
s = 'A=5, b=7'
eval('dict(%s)' % s, {'__builtins__': None, 'dict': dict})
Ответ 3
Конечно, вы могли бы сделать это:
>>> s = 'A=5, b=7'
>>> {k: int(v) for k, v in (item.split('=') for item in s.split(','))}
{'A': 5, ' b': 7}
Но в этом случае я бы просто использовал этот более императивный код:
>>> d = {}
>>> for item in s.split(','):
k, v = item.split('=')
d[k] = int(v)
>>> d
{'A': 5, ' b': 7}
Ответ 4
Как насчет этого кода:
a="A=5, b=9"
b=dict((x, int(y)) for x, y in re.findall("([a-zA-Z]+)=(\d+)", a))
print b
Вывод:
{'A': 5, 'b': 9}
Эта версия будет работать и с другими формами ввода, например
a="A=5 b=9 blabla: yyy=100"
предоставит вам
{'A': 5, 'b': 9, 'yyy': 100}
Ответ 5
См. ответы на mgilson, почему происходит ошибка. Чтобы достичь того, чего вы хотите, вы можете использовать:
d = {name: int(value) for name,value in (x.split('=',1) for x in s.split(','))}
Для учета пробелов используйте .strip()
по мере необходимости (например: x.strip().split('=',1)
).
Ответ 6
>>> strs='A=5, b=7'
>>> {x.split('=')[0].strip():int(x.split('=')[1]) for x in strs.split(",")}
{'A': 5, 'b': 7}
для удобства чтения вы должны использовать обычный цикл for-in вместо понимания.
strs='A=5, b=7'
dic={}
for x in strs.split(','):
name,val=x.split('=')
dic[name.strip()]=int(val)
Ответ 7
Как насчет этого?
>>> s
'a=5, b=3, c=4'
>>> {z.split('=')[0].strip(): int(z.split('=')[1]) for z in s.split(',')}
{'a': 5, 'c': 4, 'b': 3}