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

发布于 2024-10-07 10:36:03 字数 705 浏览 3 评论 0原文

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

我可以举出一个合适的例子,但我认为这个问题已经足够清楚了。

下面是伪代码的示例:

[... [r for r in some_list if r.some_attribute == Something_from_within_this_list 理解] ... [r for r in some_list if r.some_attribute == Something_from_within_this_list 理解] .. .]

有没有什么方法可以避免这里的重复,并简单地为此临时列表添加一个变量,仅用于列表理解中?

澄清: 列表理解已经运行良好,所以这不是“可以用列表理解来完成”的问题。而且它也比 for 语句的原始形式更快,因此它也不是“for 语句与列表推导式”问题之一。这只是一个通过单独为列表理解内部变量设置变量名来使列表理解更具可读性的问题。只是谷歌搜索我还没有真正找到任何答案。我找到了这个这个,但这并不是我真正想要的。

Like the title says, is there any way to name variables (i.e., lists) used within a nested list comprehension in Python?

I could come up with a fitting example, but I think the question is clear enough.

Here is an example of pseudo code:

[... [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] ...]

Is there any way to avoid the repetition here and simply add a variable for this temporary list only for use within the list comprehension?

CLARIFICATION:
The list comprehension is already working fine, so it's not a question of 'can it be done with a list comprehension'. And it is quicker than it's original form of a for statement too, so it's not one of those 'for statements vs list comprehensions' questions either. It is simply a question of making the list comprehension more readable by making variable names for variables internal to the list comprehension alone. Just googling around I haven't really found any answer. I found this and this, but that's not really what I am after.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

半山落雨半山空 2024-10-14 10:36:03

根据我对你想做的事情的理解,不,你做不到。

您不能在列表推导式中执行作业,因为列表推导式本质上是这样的形式

[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 的解决方案通常是 burly 列表推导式的一个很好的替代方案。

Based on my understanding of what you want to do, No you cannot do it.

You cannot carry out assignments in list comprehensions because a list comprehension is essentially of the form

[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)]

Granted there are a few other cases but they're all about like that. Note that nowhere does there exist room for a statement which is what a name assignment is. So you cannot assign to a name in the context of a list comprehension except by using the for my_variable in syntax.

If you have the list comprehension working, you could post it and see if it can be simplified. Solutions based on itertools are often a good alternative to burly list comprehensions.

长途伴 2024-10-14 10:36:03

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

让我用一个例子来解释一下:

我只是想解决一个毕达哥拉斯三元组,其总和为 1000。解决它的 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-ab),我想将结果存储在内部变量中以避免冗余计算。我发现做到这一点的唯一方法是添加另一个带有单个值的循环来声明内部变量:

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 秒
  • 第二种方法:0.087 秒
  • 第三种方法:0.109 秒

I think I understand exactly what you meant, and I came up with a "partial solution" to this problem. The solution works fine, but is not efficent.

Let me explain with an example:

I was just trying to solve a Pythagorean triplet which sum was 1000. The python code to solve it is just:

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

But I wanted to code it in a functional programming-like style:

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)

As can be seen in the code, I calc 3 times (sum-a-b), and I wanted to store the result in an internal varible to avoid redundant calculation. The only way I found to do that was by adding another loop with a single value to declare an internal variable:

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)

It works fine... but as I said at the begin of the post, is not an efficent method. Comparing the 3 methods with cProfile, the time required for each method is the next one:

  • First method: 0.077 seconds
  • Secnd method: 0.087 seconds
  • Third method: 0.109 seconds
纸短情长 2024-10-14 10:36:03

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

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 的计算成本很高,则这种方法特别方便。因为它有点不寻常,所以记录“赋值”行可能是个好主意,就像我上面所做的那样。

Some people could classify the following as a "hack", but it is definitely useful in some cases.

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))

This approach is particularly convenient if the function f is costly to evaluate. Because it is somewhat unusual, it may be a good idea to document the "assignment" line, as I did above.

蝶舞 2024-10-14 10:36:03

我只是在这里冒险,因为我不知道你到底想做什么。我只是猜测你试图将超出应有的程度强行塞入单一表达中。不要这样做,只需将子表达式分配给变量即可:

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

I'm just gonna go out on a limb here, because I have no idea what you really are trying to do. I'm just going to guess that you are trying to shoehorn more than you should be into a single expression. Don't do that, just assign subexpressions to variables:

sublist = [r for r in some_list if r.some_attribute == something_from_within_this_list comprehension]
composedlist = [... sublist ... sublist ...]
2024-10-14 10:36:03

此功能已在 Python 3.8 中添加(请参阅 PEP 572),称为“赋值表达式”,运算符为 := 。

文档中的示例:

结果 = [(x, y, x/y) for x in input_data if (y := f(x)) > 0]

stuff = [[y := f(x), x/y] for x in range(5)]

This feature was added in Python 3.8 (see PEP 572), it's called "assignment expressions" and the operator is := .

Examples from the documentation:

results = [(x, y, x/y) for x in input_data if (y := f(x)) > 0]

stuff = [[y := f(x), x/y] for x in range(5)]

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文