Python 中对象名称中 <locals> 语法的函数闭包和含义

Function closures and meaning of <locals> syntax in object name in Python

假设我有以下代码:

def outer(information):
    print(locals())
    def inner():
        print("The information given to me is: ", information)
    return inner


func1 = outer("info1")
print(func1)

它returns:

{'information': 'info1'}
<function outer.<locals>.inner at 0x1004d9d30>

当然,如果我调用func1,它会在语句中打印info1。因此,通过在外部函数中打印 locals(),我可以看出局部作用域与参数存储之间存在某种关系。

我原以为 func1 只是 outer.inner,为什么语法却变成了 outer.<locals>.inner?这是一种语法方式来阐明这些函数中的每一个都有不同的局部作用域 - 想象一下我做了另一个 func2 = outer("info2") - 我 return 使用外部函数?

此外,围绕名称使用的封闭 <> 语法有什么特别之处吗?我在对象和当地人周围都看到了它。

你可以把outer.<locals>.inner想成是说inner是函数创建的局部变量。 inner 是计算机科学中所说的闭包。粗略地说,闭包就像一个 lambda,因为它充当一个函数,但它需要非全局数据与其捆绑在一起才能运行。在内存中,它充当信息和对被调用函数的引用之间的元组。

foo = outer("foo")
bar = outer("bar")

# In memory these more or less looks like the following:
("foo", outer.inner)
("bar", outer.inner)

# And since it was created from a local namespace and can not be accessed
# from a static context local variables bundled with the function, it
# represents that by adding <local> when printed.

# While something like this looks a whole lot more convenient, it gets way
# more annoying to work with when the local variables used are the length of
# your entire terminal screen.
<function outer."foo".inner at 0x1004d9d30>

除了告诉您 <local> 有一些特殊含义外,<> 本身并没有什么特别之处。


编辑:

我在写我的答案时并不完全确定,但在看到@wim 的答案后 <local> 不仅适用于在本地上下文中创建的消费变量的闭包。它可以更广泛地应用于在本地命名空间内创建的所有函数(或任何其他函数)。所以总而言之,foo.<local>.bar 只是意味着“bar 是在 foo 的本地命名空间中创建的”。

参见 PEP 3155 -- Qualified name for classes and functions and the example with nested functions

For nested classes, methods, and nested functions, the __qualname__ attribute contains a dotted path leading to the object from the module top-level. A function's local namespace is represented in that dotted path by a component named <locals>.

由于函数的 __repr__ 使用 __qualname__ 属性,打印嵌套函数时您会在输出中看到这个额外的组件。

I was expecting func1 to simply be outer.inner

这不是完全合格的名称。使用此 repr,您可能会错误地认为您可以导入名称 outer 并动态访问属性 inner。请记住,qualname 是“指向对象的虚线路径”,但在这种情况下,属性访问是不可能的,因为 inner 是局部变量。

Also, is there something special about the enclosing <> syntax when used around a name?

它没有什么特别之处,但是它给了程序员一个非常强烈的提示,你不能直接访问这个命名空间,因为名字不是a valid identifier.