为什么类定义总是产生相同的字节码? [英] Why does a class definition always produce the same bytecode?

查看:77
本文介绍了为什么类定义总是产生相同的字节码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我做:

#!/usr/bin/env python
# encoding: utf-8

class A(object):
    pass

现在我反汇编它:

python -m dis test0.py 
  4           0 LOAD_CONST               0 ('A')
              3 LOAD_NAME                0 (object)
              6 BUILD_TUPLE              1
              9 LOAD_CONST               1 (<code object A at 0x1004ebb30, file "test0.py", line 4>)
             12 MAKE_FUNCTION            0
             15 CALL_FUNCTION            0
             18 BUILD_CLASS         
             19 STORE_NAME               1 (A)
             22 LOAD_CONST               2 (None)
             25 RETURN_VALUE        

现在我在类定义中添加一些语句:

Now I add some statements in the class definition:

#!/usr/bin/env python
# encoding: utf-8

class A(object):
    print 'hello'
    1+1
    pass

然后我再次拆卸:

  4           0 LOAD_CONST               0 ('A')
              3 LOAD_NAME                0 (object)
              6 BUILD_TUPLE              1
              9 LOAD_CONST               1 (<code object A at 0x1004ebb30, file "test0.py", line 4>)
             12 MAKE_FUNCTION            0
             15 CALL_FUNCTION            0
             18 BUILD_CLASS         
             19 STORE_NAME               1 (A)
             22 LOAD_CONST               2 (None)
             25 RETURN_VALUE        

做什么新语句不会出现在新字节码中吗?

What don't the new statements appear in the new bytecode?

推荐答案

新语句存储在嵌套中字节码。您可以在反汇编中看到另一个代码对象已加载:

The new statements are stored in nested bytecode. You can see in your disassembly that another code object is loaded:

      9 LOAD_CONST               1 (<code object A at 0x1004ebb30, file "test0.py", line 4>)

您需要检查改为那个代码对象。这是因为类主体的执行就像一个函数对象一样,然后使用调用产生的本地名称空间来形成类成员。

You need to inspect that code object instead. That's because the class body is executed just like a function object, and the local namespace that call produces is then used to form the class members.

Demo:

>>> import dis
>>> def wrapper():
...     class A(object):
...         pass
... 
>>> dis.dis(wrapper)
  2           0 LOAD_CONST               1 ('A')
              3 LOAD_GLOBAL              0 (object)
              6 BUILD_TUPLE              1
              9 LOAD_CONST               2 (<code object A at 0x104b99930, file "<stdin>", line 2>)
             12 MAKE_FUNCTION            0
             15 CALL_FUNCTION            0
             18 BUILD_CLASS         
             19 STORE_FAST               0 (A)
             22 LOAD_CONST               0 (None)
             25 RETURN_VALUE        
>>> dis.dis(wrapper.__code__.co_consts[2])
  2           0 LOAD_NAME                0 (__name__)
              3 STORE_NAME               1 (__module__)

  3           6 LOAD_LOCALS         
              7 RETURN_VALUE        

这与您的第一个示例相同;通过 wrapper .__ code __。co_consts 元组访问类主体,这是 LOAD_CONST 字节码所引用的;索引为 2

This is the same setup as your first sample; the class body is accessed via the wrapper.__code__.co_consts tuple, which is what the LOAD_CONST byte code refers to; the index is given as 2.

现在我们可以添加类主体:

Now we can add a class body:

>>> def wrapper():
...     class A(object):
...         print 'hello'
...         1+1
...         pass
... 
>>> dis.dis(wrapper)
  2           0 LOAD_CONST               1 ('A')
              3 LOAD_GLOBAL              0 (object)
              6 BUILD_TUPLE              1
              9 LOAD_CONST               2 (<code object A at 0x104b4adb0, file "<stdin>", line 2>)
             12 MAKE_FUNCTION            0
             15 CALL_FUNCTION            0
             18 BUILD_CLASS         
             19 STORE_FAST               0 (A)
             22 LOAD_CONST               0 (None)
             25 RETURN_VALUE        
>>> dis.dis(wrapper.__code__.co_consts[2])
  2           0 LOAD_NAME                0 (__name__)
              3 STORE_NAME               1 (__module__)

  3           6 LOAD_CONST               0 ('hello')
              9 PRINT_ITEM          
             10 PRINT_NEWLINE       

  4          11 LOAD_CONST               2 (2)
             14 POP_TOP             

  5          15 LOAD_LOCALS         
             16 RETURN_VALUE        

现在出现班级正文;我们可以看到加载类主体时将执行的字节码。

Now the class body appears; we can see the byte code that'll be executed when the class body is loaded.

值得注意的是 LOAD_NAME 和为每个类正文执行的 STORE_NAME 字节码;它们检索模块名称并将其存储为新的本地名称 __ module __ ,这样您的类将以 __ module __ 属性一旦创建。

Of note are the LOAD_NAME and STORE_NAME bytecodes executed for each class body; those retrieve the module name and store those as a new local name __module__, so that your class will end up with a __module__ attribute once created.

然后, LOAD_LOCALS 字节码收集此函数中产生的所有本地名称并返回给调用者,以便 BUILD_CLASS 字节码可以与'A'字符串和 object 基元组(使用 BUILD_TUPLE 创建)可以生成新的类对象。

The LOAD_LOCALS bytecode then gathers all the local names produced in this 'function' and returns that to the caller, so that the BUILD_CLASS bytecode can use that together with the 'A' string and the object bases tuple (created with BUILD_TUPLE) can produce your new class object.

这篇关于为什么类定义总是产生相同的字节码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆