【问题标题】:Python: function foo() in the "for num in foo()" loop multiple times called? [duplicate]Python:多次调用“for num in foo()”循环中的函数 foo()? [复制]
【发布时间】:2016-08-04 07:24:30
【问题描述】:

是否在循环的每次重复中调用 foo()?

for num in foo():
    # Do something

如果这样效率低下,这段代码更好吗?

l = foo()
for num in l:
    # Do something

【问题讨论】:

    标签: python python-3.x for-loop


    【解决方案1】:

    没有。在两者中,foo() 都只被调用一次。可以预期前者比后者稍快。此外,list 是内置函数/类型的名称,您不应将其用作变量名称。


    您可以使用 Python 字节码反汇编器dis.dis 找出 CPython 生成的字节码:

    >>> import dis
    >>> dis.dis(compile('for num in foo():pass', '', 'exec'))
      1           0 SETUP_LOOP              17 (to 20)
                  3 LOAD_NAME                0 (foo)
                  6 CALL_FUNCTION            0 (0 positional, 0 keyword pair)
                  9 GET_ITER
            >>   10 FOR_ITER                 6 (to 19)
                 13 STORE_NAME               1 (num)
                 16 JUMP_ABSOLUTE           10
            >>   19 POP_BLOCK
            >>   20 LOAD_CONST               0 (None)
                 23 RETURN_VALUE
    

    在上面的字节码中,循环体从10 FOR_ITER 开始,一直持续到19 POP_BLOCK。比较:

    >>> dis.dis(compile('l = foo()\nfor num in list:pass', '', 'exec'))
      1           0 LOAD_NAME                0 (foo)
                  3 CALL_FUNCTION            0 (0 positional, 0 keyword pair)
                  6 STORE_NAME               1 (l)
    
      2           9 SETUP_LOOP              14 (to 26)
                 12 LOAD_NAME                1 (l)
                 15 GET_ITER
            >>   16 FOR_ITER                 6 (to 25)
                 19 STORE_NAME               2 (num)
                 22 JUMP_ABSOLUTE           16
            >>   25 POP_BLOCK
            >>   26 LOAD_CONST               0 (None)
                 29 RETURN_VALUE
    

    这里循环体从位置 16 开始,一直持续到 25。循环体的字节码是相同的;唯一的区别是额外的操作码STORE_NAMEfoo() 的返回值存储到list 中,以及额外的LOAD_NAME 用于从list 中检索值。

    【讨论】:

    • 更详细地说:如果 foo 在第一个示例中的每次迭代都被调用,那么后者更有效。事实上,无论创建和访问变量需要多长时间,后者的效率都较低。
    • 感谢您的详细解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-09
    • 1970-01-01
    • 2014-11-11
    • 2020-02-11
    • 1970-01-01
    • 2020-04-10
    • 1970-01-01
    相关资源
    最近更新 更多