python中的code object

引入

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

def f():
    pass
f.__code__
<code object f at 0x00000176FC4E8B30, file "<input>", 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']

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 虚拟机需要的栈空间
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)

函数定义时可以用‘/’划分,将’/'前面的规定全为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'

同时还可以用‘‘划分,’'后面的全部都是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

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') 出现的常量如数字,字符串

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)
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)
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',)
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pchaoda

感谢支持~~~~~~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值