【问题标题】:Python cannot use unpacking in list comprehension with ternary operatorPython 不能在列表推导中使用三元运算符解包
【发布时间】:2018-10-13 13:24:38
【问题描述】:

假设我有一本字典

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] 的错误..

我该如何解决这个问题?

【问题讨论】:

  • 可能重复 of。至少和那个问题有关

标签: python list tuples list-comprehension ternary-operator


【解决方案1】:

如果您不必使用列表推导,可以使用生成器:

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() 返回字典项的顺序进行更改。

【讨论】:

  • 你可以做if type(v) == list:isinstance(v, list)
【解决方案2】:

可以使用嵌套列表组合来完成,但它并不漂亮。一种方法是将非列表项包装到列表中,然后解压缩生成的 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)

正如 Lutz Horn 所说,如果输出列表的顺序很重要,这种解包策略会有点危险,因为传统上在 Python 中,普通的 dict 不一定保留插入顺序。但是在 Python 3.6+ 中,dicts do 保持顺序,所以这种技术是安全的,但它仍然让我有点不舒服。 ;)

【讨论】:

  • 你在列表理解中做到这一点真的很酷!
  • @Euler_Salter 谢谢!很高兴知道如何 做这样的事情。但也很高兴知道您可能不应该编写如此难以阅读的代码。 :)
  • getattr(a, 'extend' if key.endswith('list') else 'append')(val)
  • @Chris_Rands: (a.append, a.extend)[key.endswith('list')](val) :p
  • getattr(a, ['append','extend'][key.endswith('list')])(val):P
猜你喜欢
  • 2018-10-01
  • 2022-01-15
  • 2016-09-09
  • 2018-09-27
  • 2021-09-03
  • 1970-01-01
  • 2021-03-09
  • 2016-03-27
  • 2021-10-06
相关资源
最近更新 更多