Why does the inclusion of an inner function that uses a local variable change order of locals
Asked Answered
D

0

6

The following prints {'a': 'a', 'b': 'b'}:

def foo(a: str = "a", b: str = "b") -> None:
    print(locals())
foo()  # Prints {'a': 'a', 'b': 'b'}

Which I'd expect as locals in Python 3.7+ returns the order of creation.

But the below prints {'b': 'b', 'a': 'a'}

def foo(a: str = "a", b: str = "b") -> None:
    print(locals())
    lambda: a
    # or:
    # def inner() -> None:
    #     a

foo()  # Prints {'b': 'b', 'a': 'a'}

It seems like it delayed the order of variable creation, which is strange. Why is this?

Edit: Ah, this only happens with Python 3.10 and lower. I guess it's a Python issue? If anyone could find the relevant GitHub issue, please share it. I might be blind as I can't find the relevant details in the 3.11 changelogs.

Dulciana answered 12/8 at 18:32 Comment(5)
A local variable that is accessed from a nested scope is a fundamentally different thing than a normal local variable, since it can possibly outlive the function containing it. (That doesn't actually happen in your example, but if you had returned that lambda, a would have continued to exist indefinitely). It's not surprising to me that this affects its position in the locals() dict.Chemisorption
Yes, remember that locals() is a function that gathers up all the local variables, because they're not necessarily all in one place.Cos
So, this could come down to various implementation details, I don't think you will find "order changed in the dict result of calling locals()" in the changelog explicitly, because the particular order is not guaranteed by anything, as far as I am aware.Does
Why does the order matter?Philomena
@Does from Python 3.7 onwards, dict is ordered by insertion order (see What’s New In Python 3.7). Whether we can find the order change logged somewhere, I'm hopeful that it is, the 3.7 changelog and a GitHub/BPO issue (see my post for the link) has documented the locals order changes. It'd be strange that it changed again without letting anyone know.Dulciana

© 2022 - 2024 — McMap. All rights reserved.