Python не может использовать распаковку в понимании списка с троичным оператором - PullRequest
0 голосов
/ 03 мая 2018

предположим, у меня есть словарь

kwargs = {'key1': 1, 
          'key2': 2,
          'key3list': [1,2,3,4]}

Где одно из значений любого из ключей может быть списком целых чисел, тогда как остальные будут просто любым объектом, в данном случае целым числом. Я хочу, чтобы в одной строке (или не более чем в паре) все значения ключей были помещены в один кортеж, распаковывая все возможные списки. Обратите внимание, что при построении словаря kwargs ключи со списком будут иметь ключ, заканчивающийся на «список».

Я придумал следующее:

a = tuple(
[kwargs[key] if not key.endswith('list') else *kwargs[key] for key in kwargs.keys()]
)

Однако я получаю ошибку, которую не могу распаковать *kwargs[key] здесь ..

Как я мог это исправить?

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Это можно сделать, используя компоновку со вложенным списком, но это не красиво. Один из способов - обернуть элементы, не входящие в список, в списки, а затем распаковать полученный 2D-список.

kwargs = {
    'key1': 1,
    'key2': 2,
    'key3list': [1, 2, 3, 4],
}

a = [u for v in 
        [val if key.endswith('list') else [val] for key, val in kwargs.items()] 
    for u in v]
print(a)

выход

[1, 2, 1, 2, 3, 4]

Я серьезно рекомендую использовать традиционные методы зацикливания здесь, не пытайтесь делать все это в списке комп. Например,

a = []
for key, val in kwargs.items():
    if key.endswith('list'):
        a.extend(val)
    else:
        a.append(val)

print(a)

Код выше можно записать как

a = []
for key, val in kwargs.items():
    meth = a.extend if key.endswith('list') else a.append
    meth(val)

Но даже это немного «умно» и менее читабельно, чем в предыдущей версии.


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

a = []
for val in kwargs.values():
    if isinstance(val, list):
        a.extend(val)
    else:
        a.append(val)

Как отмечает Лутц Хорн, эта стратегия распаковки немного опасна, если важен порядок вывода списка, поскольку в Python традиционно простой дикт не обязательно сохраняет порядок вставки. Однако в Python 3.6+ дикты do сохраняют порядок, поэтому этот метод безопасен, но он все еще делает меня немного некомфортным. ;)

0 голосов
/ 03 мая 2018

Если вам не нужно использовать списки, генератор может быть использован:

def flat(l):
    for k, v in l.items():
        if type(v) == list:
            for x in v:  
                yield x
        else:
            yield v

kwargs = {'key1': 1,
          'key2': 2,
          'key3list': [1,2,3,4]}

print(tuple(flat(kwargs)))

Выход:

(1, 2, 1, 2, 3, 4)

Обратите внимание, что у dict нет порядка, поэтому результирующий кортеж может меняться в зависимости от порядка, в котором items() возвращает элементы словаря.

...