python - 如何在Python中的列表理解中保存重复计算?

标签 python python-3.x list-comprehension

<分区>

在以下 Python 代码中:

keyboards = [3, 1]
drivers = [5, 2, 8]
upper_limit = 10
sums = [k + d for k in keyboards for d in drivers if (k + d) <= upper_limit]

我想将 k+d 的结果存储在列表推导中,以便在列表推导中引用它。在 Python3 中可以吗?

我知道我们可以做到以下几点:

sums = []
for k in keyboards:
    for d in drivers:
        s = k + d
        if s <= upper_limit:
            sums.append(s)

但我希望避免附加的副作用操作。

最佳答案

如果您使用的是 Python 3.8 或更新版本,则可以使用 assignment operator (又名 海象运算符)在列表推导中创建一个新的本地名称并分配给它。对于您的具体示例,您将在 <= 的左侧操作数中执行此操作比较:

sums = [
    s
    for k in keyboards
    for d in drivers
    if (s := k + d) <= upper_limit
]

请注意,您必须在此处的赋值周围使用括号,因为海象运算符具有 the lowest precedence of all Python operators ;如果没有括号,您将分配 k + d <= upper_limit 的结果至 s , 所以一个 bool 值。

考虑到 s 将在周围范围内可见,名称s将具有与 sums 相同的范围有;函数内部的局部,如果在模块级别运行列表理解,则为全局。 kd ,另一方面,在列表理解循环中是局部的,在理解之外是不可见的。

演示:

>>> keyboards = [3, 1]
>>> drivers = [5, 2, 8]
>>> upper_limit = 10
>>> [s for k in keyboards for d in drivers if (s := k + d) <= upper_limit]
[8, 5, 6, 3, 9]
>>> s
9
>>> k
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'k' is not defined

在早期的 Python 版本中,只有 for 的目标中的名称循环可用于在列表理解中分配一个新名称,因此如果您需要“本地”变量来引用计算,则需要找到添加额外循环的方法。

因此在 Python 3.7 或更早版本中,您可以在计算 k + d 的单个元素元组上添加另一个循环。 :

sums = [
    s
    for k in keyboards
    for d in drivers
    for s in (k + d,)
    if s <= upper_limit
]

(k + d,)single-element tuple ,所以 for s in (k + d,)keyboards 上的每次迭代只执行一次和 drivers , 有效分配 k + ds .

您还可以使用生成器表达式来生成 k + d两个嵌套的总和 for循环,然后迭代该表达式的结果:

sums = [
    s
    for s in (
        k + d
        for k in keyboards
        for d in drivers
    )
    if s <= upper_limit
]

在后一种情况下,您可以先将该表达式存储为一个单独的变量:

s_calc = (k + d for k in keyboards for d in drivers)
sums = [s for s in s_calc if s <= upper_limit]

有了这些选项,s始终局限于理解循环,在 sums 处不可见范围级别。它不会从理解表达式中“流血”。

后面选项的演示:

>>> [s for k in keyboards for d in drivers for s in (k + d,) if s <= upper_limit]
[8, 5, 6, 3, 9]
>>> [s for s in (k + d for k in keyboards for d in drivers) if s <= upper_limit]
[8, 5, 6, 3, 9]
>>> s_calc = (k + d for k in keyboards for d in drivers)
>>> [s for s in s_calc if s <= upper_limit]
[8, 5, 6, 3, 9]

关于python - 如何在Python中的列表理解中保存重复计算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44988861/

相关文章:

python - 为什么 arrow.now() 不在包含今天的范围内?

python - 错误 "TypeError: a bytes-like object is required, not ' int'"

python - Django 电子商务中的 URL 安全

python-3.x - 如何发送包含扩展查询的 graphQL 查询?

python - 如果第一个数字和长度相同,则从列表中删除数字

python - for循环前的数字是什么意思

python - axhspan 使用坐标设置限制

python - 在 Python 中查找、删除文本并将其添加到 pdf 文件中

scala - 如何将数字列表映射到 Scala 中的增量列表?

python - 在可迭代的东西中计算匹配元素的大多数pythonic方法