[New-bugs-announce] [issue46225] f_lasti behaves differently for lambdas returned from loops

Ned Batchelder report at bugs.python.org
Sun Jan 2 08:45:09 EST 2022


New submission from Ned Batchelder <ned at nedbatchelder.com>:

Python 3.11.0a3 changed how f_lasti behaves when calling a function in some
situations.

This example shows returning a lambda from a function.  If the lambda is
returned in a loop, then frame.f_lasti is 0 when it is called.  If the lambda
is not in a loop, then f_lasti is -1, as is usual when calling a function.

This behavior first appeared in 3.11.0a3.

---< showit.py >--------------------------------------------------

import linecache, sys

def trace(frame, event, arg):
    # The weird globals here is to avoid a NameError on shutdown...
    if frame.f_code.co_filename == globals().get("__file__"):
        if event != "line":
            lineno = frame.f_lineno
            lasti = f"lasti {frame.f_lasti}" if event == "call" else ""
            line = linecache.getline(__file__, lineno).rstrip()
            print("{} {} {:10}: {}".format(event[:4], lineno, lasti, line))
    return trace

print(sys.version)
sys.settrace(trace)

def run1():
    for i in range(1):
        return lambda: i

def run2():
    return lambda: 99

f = run1()
print(f())

f = run2()
print(f())
------------------------------------------------------------------

Here are 3.10, 3.11.0a2, 3.11.0a3, and the tip of 3.11.  The changing line is
marked with <<<<<:

$ python3.10 showit.py
3.10.1 (main, Dec 14 2021, 08:30:13) [Clang 12.0.0 (clang-1200.0.32.29)]
call 16 lasti -1  : def run1():
retu 18           :         return lambda: i
call 18 lasti -1  :         return lambda: i        <<<<<
retu 18           :         return lambda: i
0
call 20 lasti -1  : def run2():
retu 21           :     return lambda: 99
call 21 lasti -1  :     return lambda: 99
retu 21           :     return lambda: 99
99

$ /usr/local/pyenv/pyenv/versions/3.11.0a2/bin/python3.11 showit.py
3.11.0a2 (main, Nov  6 2021, 07:16:30) [Clang 12.0.0 (clang-1200.0.32.29)]
call 16 lasti -1  : def run1():
retu 18           :         return lambda: i
call 18 lasti -1  :         return lambda: i        <<<<<
retu 18           :         return lambda: i
0
call 20 lasti -1  : def run2():
retu 21           :     return lambda: 99
call 21 lasti -1  :     return lambda: 99
retu 21           :     return lambda: 99
99

$ /usr/local/pyenv/pyenv/versions/3.11.0a3/bin/python3.11 showit.py
3.11.0a3 (main, Dec  9 2021, 12:22:18) [Clang 12.0.0 (clang-1200.0.32.29)]
call 16 lasti -1  : def run1():
retu 18           :         return lambda: i
call 18 lasti 0   :         return lambda: i        <<<<<
retu 18           :         return lambda: i
0
call 20 lasti -1  : def run2():
retu 21           :     return lambda: 99
call 21 lasti -1  :     return lambda: 99
retu 21           :     return lambda: 99
99

$ /usr/local/cpython/bin/python3 showit.py
3.11.0a3+ (heads/main:a82baed0e9, Jan  2 2022, 08:12:01) [Clang 12.0.0 (clang-1200.0.32.29)]
call 16 lasti -1  : def run1():
retu 18           :         return lambda: i
call 18 lasti 0   :         return lambda: i        <<<<<
retu 18           :         return lambda: i
0
call 20 lasti -1  : def run2():
retu 21           :     return lambda: 99
call 21 lasti -1  :     return lambda: 99
retu 21           :     return lambda: 99
99

----------
keywords: 3.11regression
messages: 409496
nosy: Mark.Shannon, nedbat
priority: normal
severity: normal
status: open
title: f_lasti behaves differently for lambdas returned from loops
versions: Python 3.11

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue46225>
_______________________________________


More information about the New-bugs-announce mailing list