【问题标题】:Python unpacking from list comprehension over empty inputPython从空输入的列表理解中解包
【发布时间】:2017-06-29 16:49:21
【问题描述】:

当使用一个通过元组返回多个值的函数时,我经常会发现自己使用以下惯用语从列表推导式中解压缩结果。

fiz, buz = zip(*[f(x) for x in input])

大多数情况下这工作正常,但如果input 为空,它会抛出ValueError: need more than 0 values to unpack。我能想到的解决这个问题的两种方法是

fiz = []
buz = []
for x in input:
    a, b = f(x)
    fiz.append(a)
    buz.append(b)

if input:
    fiz, buz = zip(*[f(x) for x in input])
else:
    fiz, buz = [], []

但是这些都不是 Python 风格的——前者过于冗长,而后者在输入是生成器而不是列表时不起作用(除了需要 if/else 我觉得真的不应该需要)。

有没有很好的简单方法来做到这一点?我最近大部分时间都在使用 Python 2.7,但如果它们不同,我也有兴趣了解任何 Python 3 解决方案。

【问题讨论】:

    标签: python


    【解决方案1】:

    如果 f = lambda x: (x,x**2) 则有效

    x,y = zip(*map(f,input)) if len(input) else ((),())
    

    如果input=[]x=() and y=()

    如果input=[2]x=(2,) and y=(4,)

    如果input=[2,3]x=(2,3) and y=(4,9)

    它们是元组(不是列表),但这很容易改变。

    【讨论】:

      【解决方案2】:

      我会考虑将collections.namedtuple() 用于此类事情。我相信命名元组被认为更 Pythonic,应该避免复杂的列表推导和压缩/解包的需要。


      来自documentation

      >>> p = Point(11, y=22)     # instantiate with positional or keyword arguments
      >>> p[0] + p[1]             # indexable like the plain tuple (11, 22)
      33
      >>> x, y = p                # unpack like a regular tuple
      >>> x, y
      (11, 22)
      >>> p.x + p.y               # fields also accessible by name
      33
      >>> p                       # readable __repr__ with a name=value style
      Point(x=11, y=22)
      

      【讨论】:

      • 我对@9​​87654324@s 很熟悉,但我看不出他们会如何提供帮助。通常,当我在做这样的事情时,fizbuz 将是两个独立的东西,它们方便或需要一起计算,但一旦解包就会单独处理。
      【解决方案3】:

      你可以使用:

      fiz = []
      buz = []
      results = [fiz, buz]
      
      for x in input:
          list(map(lambda res, val: res.append(val), results, f(x)))
      
      print(results)
      

      关于 list(map(...)) 的注意事项:在 Python3 中,map 返回一个生成器,所以如果我们想要执行 lambda,就必须使用它。list 会这样做。

      (改编自我对Pythonic way to append output of function to several lists 的回答,您可以在其中找到其他想法。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多