Python的类闭包是如何工作的?

6 投票
1 回答
1060 浏览
提问于 2025-04-15 18:50

如果我在一个本地命名空间里创建一个类,这到底是怎么运作的呢?比如说:

>>> def foo():
...     i = 1
...     class bar(object):
...             j = i
...     return bar
... 
>>> dis(foo)
  2           0 LOAD_CONST               1 (1)
              3 STORE_DEREF              0 (i)

  3           6 LOAD_CONST               2 ('bar')
              9 LOAD_GLOBAL              0 (object)
             12 BUILD_TUPLE              1
             15 LOAD_CLOSURE             0 (i)
             18 BUILD_TUPLE              1
             21 LOAD_CONST               3 (<code object bar at 0xb74f8800, file "<stdin>", line 3>)
             24 MAKE_CLOSURE             0
             27 CALL_FUNCTION            0
             30 BUILD_CLASS         
             31 STORE_FAST               0 (bar)

  5          34 LOAD_FAST                0 (bar)
             37 RETURN_VALUE        

我特别想知道的几行是这些:

             15 LOAD_CLOSURE             0 (i)
             18 BUILD_TUPLE              1
             21 LOAD_CONST               3 (<code object bar at 0xb74f8800, file "<stdin>", line 3>)
             24 MAKE_CLOSURE             0
             27 CALL_FUNCTION            0
             30 BUILD_CLASS

我想知道的最重要的事情是,究竟是哪个函数被创建并被调用了?这个函数是把闭包(也就是一些特定的代码块)附加到类上的地方吗,还是说这个过程发生在别的地方?

1 个回答

2

整个类的内容,也就是

j = i

是一个代码对象,它在偏移量21的位置被加载,然后在偏移量27的位置通过 CALL_FUNCTION 被调用。调用的结果(局部命名空间)会和类名以及基类一起用来创建这个类。BUILD_CLASS 接受三个参数,和 type(name, bases, dict) 函数类似:

返回一个新的类型对象。这基本上是类语句的一种动态形式。名称字符串就是类名,它会成为 name 属性;基类的元组列出了基类,并成为 bases 属性;而字典则是包含类体定义的命名空间,成为 dict 属性。

还有一篇非常详细的文章 “关于Python类语句的说明”,解释了类是如何创建的。

撰写回答