【问题标题】:walrus operator: if contition with strange results海象运算符:如果条件有奇怪的结果
【发布时间】:2019-07-10 10:31:41
【问题描述】:

我在玩海象运算符 :=(与 this question 相关),这将在 python 3.8 中提供。

def f(x):
    return x**3

old_list =  = list(range(9))

这按预期工作(别介意这个例子毫无意义......):

new_list = [fx for x in old_list if (fx := f(x))  in {1, 8, 343}]
# [1, 8, 343]

这是有效的并且可以运行,但是会返回一些意想不到的东西:

new_list = [fx := f(x) for x in old_list if fx in {1, 8, 343}]
# []

这里发生了什么?

【问题讨论】:

    标签: python python-3.x python-3.8


    【解决方案1】:

    TL;DR 你的第二个不是“那个”有效的:

    >>> old_list = list(range(9))
    >>> f = lambda x: x ** 3
    >>> [fx := f(x) for x in old_list if fx in {1, 8, 343}]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 1, in <listcomp>
    NameError: name 'fx' is not defined
    >>> 
    

    说明

    在您的第一个列表理解中,[fx for x in old_list if (fx := f(x)) in {1, 8, 343}]fx := 在其外部创建一个变量:

    >>> old_list = list(range(9))
    >>> f = lambda x: x ** 3
    >>> [fx for x in old_list if (fx := f(x))  in {1, 8, 343}]
    [1, 8, 343]
    >>> fx
    512
    

    如果你之后运行[fx := f(x) for x in old_list if fx in {1, 8, 343}],它会变成这样:

    • for x in old_list 将 x 绑定到 0
    • if fx in {1, 8, 343},fx 是旧的 512,这是错误的
    • 由于if为假,“select”(左)部分没有执行,没有调用f,没有重新绑定fx,fx还是512。
    • 将 x 指定为 old_list 的第二个元素,即 1
    • ...

    我们可以像这样仔细检查这个解释:

    >>> [print("no no no") for x in old_list if fx in {1, 8, 343}]
    []
    

    no no no 永远不会被打印,所以这一面永远不会被执行(因为fx 是 512,而不是在 set 中)。

    【讨论】:

    • 哦; fx 已泄漏到全局命名空间(保持解释器打开),这就是它看起来正常工作的原因!你是对的!
    猜你喜欢
    • 2015-02-24
    • 2023-01-16
    • 2012-10-24
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多