当前位置: 首页 > 面试题库 >

为什么在for循环中允许使用任意目标表达式?

李安歌
2023-03-14
问题内容

我不小心写了一些这样的代码:

foo = [42]
k = {'c': 'd'}

for k['z'] in foo:  # Huh??
    print k

但是令我惊讶的是,这不是语法错误。而是打印{'c': 'd', 'z': 42}

我的 猜测 是将代码按字面意思翻译为:

i = iter(foo)
while True:
    try:
        k['z'] = i.next()  # literally translated to assignment; modifies k!
        print k
    except StopIteration:
        break

但是…语言为什么允许这样做?我希望for-
stmt的target表达式中
只允许使用单个标识符和标识符元组。在任何情况下实际上都有用吗,而不仅仅是奇怪的陷阱?


问题答案:

for循环遵循标准的分配规则,因此适用于for原始分配的LHS的内容应与以下各项一起使用:

使用分配的标准规则将每个项目依次分配到目标列表

for结构简单地调用了分配给目标的基本机制,在您的示例代码中,该机制为STORE_SUBSCR

>>> foo = [42]
>>> k = {'c': 'd'}
>>> dis.dis('for k["e"] in foo: pass')
  1           0 SETUP_LOOP              16 (to 18)
              2 LOAD_NAME                0 (foo)
              4 GET_ITER
        >>    6 FOR_ITER                 8 (to 16)
              8 LOAD_NAME                1 (k)
             10 LOAD_CONST               0 ('e')
             12 STORE_SUBSCR <--------------------
             14 JUMP_ABSOLUTE            6
        >>   16 POP_BLOCK
        >>   18 LOAD_CONST               1 (None)
             20 RETURN_VALUE

但是令我惊讶的是,这不是语法错误

显然,在常规任务中,任何有效的方法如下:

完整切片分配

>>> for [][:] in []:
...    pass
... 
>>>

列表订阅

>>> for [2][0] in [42]:
...    pass
... 
>>>

字典订阅等将是有效的候选目标,唯一的例外是 链接分配 ;但是,我暗中认为可以编写一些肮脏的语法来执行链接。

我希望仅单个标识符和标识符的元组

我想不出字典键作为目标的好用例。此外,在循环主体中进行字典键分配比在for子句中将其用作目标更具可读性。

但是,在常规分配中非常有用的扩展解压缩(Python 3)在for循环中也同样方便:

>>> lst = [[1, '', '', 3], [3, '', '', 6]]
>>> for x, *y, z in lst:
...    print(x,y,z)
... 
1 ['', ''] 3
3 ['', ''] 6

这里还召唤了分配给不同目标的相应机制。多个STORE_NAMEs:

>>> dis.dis('for x, *y, z in lst: pass')
  1           0 SETUP_LOOP              20 (to 22)
              2 LOAD_NAME                0 (lst)
              4 GET_ITER
        >>    6 FOR_ITER                12 (to 20)
              8 EXTENDED_ARG             1
             10 UNPACK_EX              257
             12 STORE_NAME               1 (x) <-----
             14 STORE_NAME               2 (y) <-----
             16 STORE_NAME               3 (z) <-----
             18 JUMP_ABSOLUTE            6
        >>   20 POP_BLOCK
        >>   22 LOAD_CONST               0 (None)
             24 RETURN_VALUE

证明afor是几乎不连续执行的赋值语句。



 类似资料:
  • 问题内容: 我只是发现我认为PLSQL与Oracle中的SQL有点意外的行为。 如果我在SQLDeveloper上运行此查询,则会得到5个结果: 但是,如果我在SQLDeveloper中运行以下语句: 变量 w_counter 以值1(怪异)结束 但最奇怪的部分是,如果我将查询封装在子查询中…… 该 w_counter 变量完成与价值5 … 你对此有什么要说的? 我正在使用Oracle 9.2i

  • } 链接:https://www.hackerrank.com/challenges/java-string-compare/problem

  • 在我的程序中,我发现当为时,循环无法正确退出。它看起来像整数溢出,远远大于10,循环不会停止。请告诉我发生了什么,以及如何在大型项目中避免这个错误。 代码链接

  • 问题内容: 有人可以向我解释此Python代码段的最后一行吗? 只是另一类。我不明白如何使用循环将对象存储到对象中。 问题答案: 您要询问的代码行是使用列表推导创建一个列表,并将在此列表中收集的数据分配给。相当于 说明 : 为了最好地解释它是 如何 工作的,可以使用一些简单的示例来帮助您 理解 所拥有的代码。如果您要继续使用Python代码,则将再次遇到列表理解,您可能想自己使用它。 注意,在下面

  • 本文向大家介绍为什么在JavaScript数组迭代中使用“ for…in”循环是个坏主意?,包括了为什么在JavaScript数组迭代中使用“ for…in”循环是个坏主意?的使用技巧和注意事项,需要的朋友参考一下 在大多数情况下,通常最好使用' for '循环而不是“ for ... in ”循环,因为“ for ... in ”循环会产生索引 ,而不会打扰剩余的索引普通的“ for ”循环显示

  • 问题内容: 我了解此构造的工作原理: 但是我不明白为什么else在这里使用它作为关键字,因为它表明所讨论的代码仅在for块未完成时才运行,这与它的工作相反!无论我如何考虑,我的大脑都无法从for陈述到else障碍的无缝发展。对我来说,还是更有意义(我正在尝试训练自己这样阅读)。 我想知道Python编码人员是如何在头脑中读取这个结构的。也许我缺少使这些代码块更容易理解的东西? 问题答案: 即使是经

  • 我在解析JSON对象时发现了这段示例代码,我对它有点了解,但希望得到更详细的解释: 我知道这是拆分记录,以得到单个记录由新的行字符,但我想知道为什么它看起来这么复杂?是不是我们不能有这样的东西: 那么括号做什么呢?为什么我们在 谢谢

  • 当我试图在PHP中操作大量数组并将结果作为HTTP POST请求的响应返回时,我遇到了一个致命错误: 允许内存大小536870912字节已用尽 我已经尝试设置以查看是否得到结果,但没有得到任何类型的响应。邮递员在我试图发出邮寄请求时总是崩溃。 数组的起始结构是这个。机身尺寸约为25mb。主阵列包含大约22k个具有此结构的阵列,我刚刚包括2个: 下面是php部分,用于操纵数组,以便通过分解每个用户的