• python中的code object


    引入

    看一段python代码,打印一个函数的__code__,返回的是一个code object,code object是什么,有哪些属性呢?

    def f():
        pass
    f.__code__
    <code object f at 0x00000176FC4E8B30, file "", line 1>
    dir(f.__code__)
    ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_kwonlyargcount', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_posonlyargcount', 'co_stacksize', 'co_varnames', 'replace']
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    code object的各个属性的含义可以参考官方文档code object属性含义

    co_argcountnumber of arguments (not including keyword only arguments, * or ** args)
    co_codestring of raw compiled bytecode
    co_cellvarstuple of names of cell variables (referenced by containing scopes)
    co_conststuple of constants used in the bytecode
    co_filenamename of file in which this code object was created
    co_firstlinenonumber of first line in Python source code
    co_flagsbitmap of CO_* flags, read more here
    co_lnotabencoded mapping of line numbers to bytecode indices
    co_freevarstuple of names of free variables (referenced via a function’s closure)
    co_posonlyargcountnumber of positional only arguments
    co_kwonlyargcountnumber of keyword only arguments (not including ** arg)
    co_namename with which this code object was defined
    co_qualnamefully qualified name with which this code object was defined
    co_namestuple of names other than arguments and function locals
    co_nlocalsnumber of local variables
    co_stacksizevirtual machine stack space required
    co_varnamestuple of names of arguments and local variables

    概念

    code object是一段可执行的python代码在CPython中的内部表示,包含一系列直接操作虚拟机内部状态的指令
    可执行的python代码包括函数,模块,,生成器表达式
    当运行一段代码时,程序被解析,编译成字节码,并被CPython虚拟机执行

    尝试

    容易理解的几个
    def f():
        pass
    
    
    code = f.__code__
    print(code.co_code)  # b'd\x00S\x00' 字节码
    print(code.co_name)  # f 函数名
    print(code.co_filename)  # D:\learn_py\code_object.py 文件名
    print(code.co_lnotab)  # b'\x00\x01' encoded mapping of line numbers to bytecode indices 行号与字节码的映射
    print(code.co_flags)  # 67 https://docs.python.org/3/library/inspect.html?highlight=__code__#inspect-module-co-flags
    print(code.co_stacksize)  # 1 virtual machine stack space required 虚拟机需要的栈空间
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    count

    co_argcount 表示除keyword only arguments, * or ** args外的参数个数
    co_posonlyargcount表示positional only arguments个数
    co_kwonlyargcount表示keyword only arguments (not including ** arg)

    def f(a, b=2, *args, **kwargs):
        pass
    
    
    code = f.__code__
    
    print(code.co_argcount)  # 2 number of arguments (not including keyword only arguments, * or ** args),不包括only keyword
    print(code.co_posonlyargcount)  # 0 number of positional only arguments
    print(code.co_kwonlyargcount)  # 0 number of keyword only arguments (not including ** arg)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    函数定义时可以用‘/’划分,将’/'前面的规定全为positional only arguments

    def f(a, b=2, /, *args, **kwargs):
        pass
    
    
    code = f.__code__
    
    print(code.co_argcount)  # 2 number of arguments (not including keyword only arguments, * or ** args),不包括only keyword
    print(code.co_posonlyargcount)  # 2 number of positional only arguments
    print(code.co_kwonlyargcount)  # 0 number of keyword only arguments (not including ** arg)
    f(1, 1)
    f(1)
    f(a=1)  # 报错TypeError: f() missing 1 required positional argument: 'a'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    同时还可以用‘‘划分,’'后面的全部都是keyword only arguments

    def f(a, *, b=2, **kwargs):
        pass
    
    
    code = f.__code__
    
    print(code.co_argcount)  # 1 number of arguments (not including keyword only arguments, * or ** args),不包括only keyword
    print(code.co_posonlyargcount)  # 0 number of positional only arguments
    print(code.co_kwonlyargcount)  # 1 number of keyword only arguments (not including ** arg)
    
    f(a=1)
    f(1)
    f(1, 2)  # TypeError: f() takes 1 positional argument but 2 were given
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    names
    def f(a):
        import math as m
        b = a.attr
        c = 2
        e = 3
        f1 = "xxxx"
        d1 = c + b
        return b
    import dis
    dis.dis(f)
    
    code = f.__code__
    print(code.co_nlocals)  # 7 局部变量的数量,等于co_varnames的size
    print(code.co_varnames)  # ('a', 'm', 'b', 'c', 'e', 'f1', 'd1') local variables 的string
    print(code.co_names)  # ('math', 'attr') 除了co_varnames,co_cellvars, co_freevars之外的其他
    print(code.co_cellvars)
    print(code.co_freevars)
    print(code.co_consts)  # (None, 0, 2, 3, 'xxxx') 出现的常量如数字,字符串
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    co_cellvars和co_freevars常在闭包中成对出现,co_freevars表示用到了scope之外的变量,co_cellvars表示变量被其他scope使用

    def g():
        a = {}
    
        def f():
            pass
        return f
    
    
    code = g.__code__
    print(code.co_varnames)
    print(code.co_cellvars)
    print(code.co_freevars)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    def g():
        a = {}
    
        def f():
            a["name"] = "haha"
            pass
        return f
    
    
    code = g.__code__
    print(code.co_varnames)  # ('f',)
    print(code.co_cellvars)  # ('a',)
    print(code.co_freevars)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    def g():
        a = {}
    
        def f():
            a["name"] = "haha"
            pass
        return f
    
    
    code = g().__code__
    print(code.co_varnames)
    print(code.co_cellvars)
    print(code.co_freevars)  # ('a',)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    凭什么测试/开发程序员工资那么高?
    自动推理的逻辑04-命题微积分
    R语言使用caret包的featurePlot函数可视化变量的重要性、通过分组数据分布差异查看变量对于预测目标变量的判别性、通过可视化密度图进行判别分析
    TPA3045-ASEMI光伏二极管TPA3045
    MYSQL--未提交(read uncommitted)、读已提交(read committed)和repeatable read(可重复读)
    Java PrintWriter.println()方法的功能简介说明
    计算机提示d3dcompiler43.dll缺失怎么修复,多个解决方法分享
    Docker安装pgAdmin4
    机器学习8-人工神经网络
    19.支持向量机-优化目标和大间距直观理解
  • 原文地址:https://blog.csdn.net/u010376229/article/details/127837419