闭包__class __

时间:2016-01-02 06:13:02

标签: python python-3.x closures python-internals

我最近逐步完成了CPython源代码,特别是在编译期间查看了类的symbol table entry

我碰到了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 __ 的含义,即什么时候类的局部变量转换为单元格变量?理想情况下,在执行过程中实际显示此行为的示例将非常棒。

1 个答案:

答案 0 :(得分:2)

Github’s blame view for that line of code告诉我们它已添加到this commit中,引用Issue #12370:防止类主体干扰__class__闭包。

从错误报告中,我们试图解决的问题类型的一个例子是:

  

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

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

    @property
    def __class__(self):
        return int

print (isinstance(X(), int))

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

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

  

补丁基本上会导致以下类声明:

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

大致如下编译:

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__的处理可能在最终补丁中发生了变化。