2014-12-12 1 views
0

Во время игры с проверкой входных данных, в частности, проверяя, имеют ли предоставленные данные все необходимые атрибуты и отбрасывают атрибуты, которые мне не нужны, я сделал что-то вроде этого:Понимание словаря Python для копирования некоторых пар в новый словарь

>>> input = {'v1': 'val1', 'a2':'val2', 'a3':'val3'} 
>>> print input 
{'v1': 'val1', 'a3': 'val3', 'a2': 'val2'} 
>>> goodkeys = ['a2', 'a3'] 
>>> print goodkeys 
['a2', 'a3'] 
>>> output = {} 
>>> for a in goodkeys:  
... output[a] = input[a] 
... 
>>> 
>>> print output 
{'a3': 'val3', 'a2': 'val2'} 

Это, конечно, работает. Но мне пришло в голову, что это возможно сделать более питоническим способом. Я пробовал:

>>> output = {} 
>>> print output 
{} 
>>> output = { a:v for a in goodkeys for v in input[a] } 
>>> print output 
{'a3': '3', 'a2': '2'} 
>>> 

Который на полсекунды считал сработавшим, тогда я понял, что значения ошибочны. Есть ли хороший метод Python? И что случилось, где Python получил эти ценности?

+0

Если 'input' не содержит один из хороших ключей, скажем,' a2' - что вы хотите, чтобы произошло? – georg

+0

Пожалуйста, не используйте 'input' в качестве имени переменной; это ключевое слово в python 3. – palsch

ответ

0
output = { a:input[a] for a in goodkeys } 

Ваш второй for выполняет итерацию по символам строковых значений.

3

Вы можете использовать dictionary view objects:

goodkeys = {'a2', 'a3'} 
output = {a: input[a] for a in input.viewkeys() & goodkeys} 

где goodkeys представляет собой набор; dict.viewkeys() создает объект, похожий на набор, который отражает содержимое словаря, а & goodkeys создает пересечение между этими клавишами и набором goodkeys. Таким образом, вы только создаете ключи, которые находятся во входном словаре и в наборе хороших клавиш.

Вы создали вложенный цикл, как это:

for a in goodkeys: 
    for v in input[a]: 
     # v is a single character in the string value 

Демо:

>>> input = {'v1': 'val1', 'a2':'val2', 'a3':'val3'} 
>>> goodkeys = {'a2', 'a3'} 
>>> {a: input[a] for a in input.viewkeys() & goodkeys} 
{'a3': 'val3', 'a2': 'val2'} 

Поскольку input[a] является строкой, то ваш внутренний цикл производства отдельных символов каждого значения:

>>> for a in goodkeys: 
...  for v in input[a]: 
...   print a, v 
... 
a3 v 
a3 a 
a3 l 
a3 3 
a2 v 
a2 a 
a2 l 
a2 2 

Ключи должны быть уникальными, поэтому для a2, один из v, a, l и 2 выбрано с остальными отброшенными. Понимание словаря устанавливает 'a2': 'v' сначала, затем 'a2': 'a' и т. Д., И только 'a2': '2' остается на выходе, в конце.

Вам не нужно было использовать этот внутренний цикл; Вы могли бы застрять с:

{a: input[v] for a in goodkeys} 

за исключением того, что если есть какие-либо ключи в goodkeys, которые не в input вы получите KeyError. Подход словарного обзора аккуратно обходит эту проблему.

+0

'KeyError's также можно было бы избежать, просто используя' {a: input [a] для a в полезных клавишах, если a in input} 'вместо использования' dict.viewkeys() 'и нахождения пересечения. Одно из преимуществ заключается в том, что он будет работать в версиях Python до версии 2.7, а это когда «viewkeys()» был введен. – martineau

+0

@martineau: конечно, но OP заявила, что они используют 2.7, а операция пересечения выполняется * один раз *, в C, и, таким образом, быстрее, чем операция тестирования членства на каждой итерации. –

+0

Да, но вы отредактировали тот факт, что они использовали версию 2.7 из вопроса ... так что теперь это более общий. – martineau

0

Возможно, вы думаете об этом. Просто попробуйте изменить

output = { a:v for a in goodkeys for v in input[a] } 

просто ...

output = { a:input[a] for a in goodkeys }