在Python中嵌套列表推导中命名变量?

时间:2010-12-13 04:10:54

标签: python nested list-comprehension

就像标题所说,有没有办法命名Python中嵌套列表理解中使用的变量(即列表)?

我可以提出一个合适的例子,但我认为问题很清楚。

以下是伪代码的示例:

[... [r for r in some_list if r.some_attribute == something_from_within_this_list comprehension] ... [r for r in some_list if r.some_attribute == something_from_within_this_list comprehension] ...]

有没有办法避免重复这里,只是为列表理解中的临时列表添加一个变量?

澄清: 列表理解已经正常工作,所以这不是“可以通过列表理解完成”的问题。它也比for语句的原始形式更快,所以它也不是那些'对于陈述与列表理解'的问题之一。这只是一个问题,通过为列表推导内部的变量创建变量名来使列表理解更具可读性。只是在谷歌上搜索我还没有找到任何答案。我找到了thisthis,但这并不是我所追求的。

4 个答案:

答案 0 :(得分:3)

根据我对你想做什么的理解,不,你做不到。

您无法在列表推导中执行任务,因为列表理解基本上是以

形式
[expression(x, y) for x in expression_that_creates_a_container 
                  for y in some_other_expression_that_creates_a_container(x)
                  if predicate(y, x)]

当然还有其他一些案例,但他们都是这样的。请注意,没有任何地方存在语句的空间,这就是名称分配。因此,除了使用for my_variable in语法之外,您无法在列表推导的上下文中指定名称。

如果你有列表理解工作,你可以发布它,看看它是否可以简化。基于itertools的解决方案通常是对魁梧列表推导的一种很好的替代方法。

答案 1 :(得分:2)

我想我完全理解你的意思,我想出了一个解决这个问题的“部分解决方案”。解决方案工作正常,但效果不高。

让我用一个例子来解释:

我只是想解决一个总和为1000的Pythagorean三元组。解决它的python代码只是:

def pythagoreanTriplet(sum):
    for a in xrange(1, sum/2):
        for b in xrange(1, sum/3):
            c = sum - a - b
            if c > 0 and c**2 == a**2 + b**2:
               return a, b, c

但我想用类似函数编程的方式对其进行编码:

def pythagoreanTriplet2(sum):
    return next((a, b, sum-a-b) for a in xrange(1, sum/2) for b in xrange(1, sum/3) if (sum-a-b) > 0 and (sum-a-b)**2 == a**2 + b**2)

从代码中可以看出,我计算了3次(sum-a-b),我想将结果存储在内部变量中以避免冗余计算。我发现这样做的唯一方法是添加另一个带有单个值的循环来声明一个内部变量:

def pythagoreanTriplet3(sum):
    return next((a, b, c) for a in xrange(1, sum/2) for b in xrange(1, sum/3) for c in [sum-a-b] if c > 0 and c**2 == a**2 + b**2)

它工作得很好......但正如我在帖子开头所说的那样,并不是一种有效的方法。将3种方法与cProfile进行比较,每种方法所需的时间是下一个:

  • 第一种方法:0.077秒
  • Secnd方法:0.087秒
  • 第三种方法:0.109秒

答案 2 :(得分:1)

有些人可能会将以下内容归类为“黑客”,但在某些情况下肯定会有用。

f = lambda i,j: int(i==j) #A dummy function (here Kronecker's delta)    
a = tuple(tuple(i + (2+f_ij)*j + (i + (1+f_ij)*j)**2
                for j in range(4)
                for f_ij in (f(i,j),) ) #"Assign" value f(i,j) to f_ij.
          for i in range(4) )
print(a)
#Output: ((0, 3, 8, 15), (2, 13, 14, 23), (6, 13, 44, 33), (12, 21, 32, 93))

如果函数f的评估成本很高,这种方法特别方便。因为它有点不寻常,所以记录“赋值”行可能是个好主意,正如我上面所做的那样。

答案 3 :(得分:0)

我要在这里走出困境,因为我不知道你到底想做什么。我只是猜测你正试图比你应该做的更多只是单一的表达。不要这样做,只需将子表达式分配给变量:

sublist = [r for r in some_list if r.some_attribute == something_from_within_this_list comprehension]
composedlist = [... sublist ... sublist ...]
相关问题