关闭超过 __class__

Closures over __class__

我最近正在单步执行 CPython 源代码,特别是在编译期间查看 symbol table entry 以获得 class。

我遇到了 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 --]

我实在看不懂,也找不到实际设置ste_needs_class_closure == 1的python代码的例子。在其他失败的尝试中,我尝试了以下方法:

class foo:
    y = 30
    def __init__(self):
        self.x = 50
    def foobar(self):
        def barfoo():
            print(self.x)
            print(y)
        return barfoo

但是即使它执行了,ste_needs_class_closure在执行期间的值是0而不是我希望的1

实际改变这个值的函数是drop_class_free,这没什么用。不幸的是,它也没有任何赞美它的评论。

实际用在analyze_block,注释为:

/* Check if any local variables must be converted to cell variables */

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

我已经尝试搜索 the changelog for Python 3.4,该成员首次出现的版本,但没有找到对它的引用。

那么,谁能解释 对 __class__ 的闭包是什么意思,也就是说,class 的局部变量何时转换为单元变量?理想情况下,一个在执行过程中实际使此行为可见的示例会很棒。

Github’s blame view for that line of code shows us that it was added in this commit, which references Issue #12370: 防止 class 实体干扰 __class__ 闭包。

根据错误报告,此尝试修复的问题类型的示例是:

In Python 3 the following code prints False because the use of super() has caused the __class__ descriptor to be omitted from the class namespace. Remove the use of super and it prints True.

class X(object):
    def __init__(self):
        super().__init__()

    @property
    def __class__(self):
        return int

print (isinstance(X(), int))

(注意这段代码使用了new super()。)

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

The patch basically causes the following class statement:

class C(A, B, metaclass=meta):
    def f(self):
        return __class__

To be compiled approximately like this:

def _outer_C(*__args__, **__kw__):
    class _inner_C(*__args__, **__kw__):
        def f(self):
            return __class__
    __class__ = _inner_C
    return _inner_C 
C = _outer_C(A, B, metaclass=meta)

…尽管后来的一些讨论表明 __args____kw__ 的处理可能在最终补丁中发生了变化。