关于__class__的闭包

Jim*_*ard 5 python closures python-3.x python-internals

我最近逐步完成了CPython源代码,特别是在编译期间查看类的符号表条目.

我碰到了typedef struct _symtable_entry结构的以下条目:

[-- other entries --]
unsigned ste_needs_class_closure : 1; /* for class scopes, true if a
                                         closure over __class__
                                         should be created */
[-- other entries --]
Run Code Online (Sandbox Code Playgroud)

我似乎无法理解它,也无法找到实际设置的python代码示例ste_needs_class_closure == 1.在其他失败的尝试中,我尝试了以下方法:

class foo:
    y = 30
    def __init__(self):
        self.x = 50
    def foobar(self):
        def barfoo():
            print(self.x)
            print(y)
        return barfoo
Run Code Online (Sandbox Code Playgroud)

但即使它执行,执行ste_needs_class_closure期间的价值0也不1是我希望的那样.

实际上改变这个值的功能对它drop_class_free没有多大帮助.不幸的是,它也没有任何赞美它的评论.

它实际上用于analyze_block评论:

/* Check if any local variables must be converted to cell variables */
Run Code Online (Sandbox Code Playgroud)

我可以理解为一个概念,但无法找到它发生的例子.

我已经尝试在Python 3.4中搜索更新日志,这是该成员首次出现的版本,但未找到对它的引用.

那么,任何人都可以解释__class__上的闭包是什么意思,即类的局部变量何时被转换为单元变量?理想情况下,在执行过程中实际显示此行为的示例将非常棒.

jbg*_*jbg 2

该代码行的 Github\xe2\x80\x99s 责任视图向我们显示它是在此提交中添加的,该提交引用了问题 #12370:防止类体干扰闭包__class__

\n\n

从错误报告来看,尝试修复的问题类型的示例是:

\n\n
\n

在 Python 3 中,会打印以下代码False,因为使用 \n super()导致__class__描述符从类命名空间中被省略。删除 的使用super并打印True

\n\n
class X(object):\n    def __init__(self):\n        super().__init__()\n\n    @property\n    def __class__(self):\n        return int\n\nprint (isinstance(X(), int))\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

(请注意,此代码使用新的 super()。)

\n\n

关于补丁的功能,也来自错误报告:

\n\n
\n

该补丁主要导致以下类语句:

\n\n
class C(A, B, metaclass=meta):\n    def f(self):\n        return __class__\n
Run Code Online (Sandbox Code Playgroud)\n\n

大约是这样编译的:

\n\n
def _outer_C(*__args__, **__kw__):\n    class _inner_C(*__args__, **__kw__):\n        def f(self):\n            return __class__\n    __class__ = _inner_C\n    return _inner_C \nC = _outer_C(A, B, metaclass=meta)\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

__args__\xe2\x80\xa6 尽管后来的一些讨论表明 和的处理__kw__可能在最终补丁中发生了变化。

\n