gpt4 book ai didi

python - 如何在python中创建代码对象?

转载 作者:太空狗 更新时间:2023-10-29 17:22:15 25 4
gpt4 key购买 nike

我想用函数类型.codeType()创建一个新的代码对象。
关于这一点,几乎没有文献记载,现有的文献说“心脏不虚弱”。
告诉我需要什么,并给我一些关于传递给types.codetype的每个参数的信息,
可能发布一个示例。
注:
在正常的用例中,您只需要内置函数compile()。
只有当您想创建新的指令,而这些指令在编写普通的源代码时无法获得,并且需要直接访问字节码时,才应该使用types.codetype()。

最佳答案

–––––––––-
免责声明:
此答案中的文档不是官方文档,可能不正确。
此答案仅对python 3.x版本有效
–––––––––-
要创建代码对象,必须将以下参数传递给函数codeType():

CodeType(
argcount, # integer
kwonlyargcount, # integer
nlocals, # integer
stacksize, # integer
flags, # integer
codestring, # bytes
consts, # tuple
names, # tuple
varnames, # tuple
filename, # string
name, # string
firstlineno, # integer
lnotab, # bytes
freevars, # tuple
cellvars # tuple
)

现在我将试着解释每个论点的含义。
argCount数
要传递给函数的参数数(*args和**kwargs不包括在内)。
KwOnlyargCount(KwOnlyargCount)
keyword-only arguments的数目。
非本地语言
局部变量数量,
即除全局名称外的所有变量和参数(*args和**kwargs)。
堆栈大小
代码所需的堆栈(虚拟机堆栈)量,
如果您想了解它的工作原理,请参阅official Documentation
旗帜
表示代码对象的位图:
1–>代码已优化
2–>newlocals:有一个新的本地命名空间(例如函数)
4–>代码接受任意数量的位置参数(*args被使用)
8–>代码接受任意数量的关键字参数(*kwargs被使用)
32–>代码是一个生成器
其他标志在旧的python版本中使用,或者被激活来表示从未来导入的内容。__
代码字符串
表示字节码指令的字节序列。
如果您想要更好的理解,请参阅(与上面相同)
阵营
包含字节码使用的文本的元组(例如预计算的数字、元组和字符串)
姓名
包含字节码使用的名称的元组。
这些名称是全局变量、函数和类,或者也是从对象加载的属性。
变量名
包含字节码使用的本地名称的元组(先是参数,然后是局部变量)
文件名
它是编译代码的文件名。
它可以是你想要的任何东西,你可以就此说谎。;)
名称
它给出了函数的名称。
这也可以是你想要的,但是要小心:
这是回溯中显示的名称,如果名称不清楚,回溯可能不清楚,
想想羔羊有多烦人。
第一行编号
函数的第一行(如果编译了源代码,则用于调试)
勒诺布
将字节码偏移量与行号关联起来的字节映射。
(我认为这也是为了调试目的,关于这方面的文档很少)
自由变量
包含自由变量名称的元组。
自由变量是在定义代码对象的命名空间中声明的变量,
它们在声明嵌套函数时使用;
这不会在模块级别发生,因为在这种情况下,自由变量也是全局变量。
细胞变
包含嵌套函数引用的局部变量名的元组。
––––––––––-
示例:
下面的例子应该澄清上述内容的含义。
注意:在完成的代码对象中,上面提到的属性具有co_u前缀,
函数将其可执行体存储在uu code_uuu属性中
––––––––––-
第一个示例
def F(a,b):
global c
k=a*c
w=10
p=(1,"two",3)

print(F.__code__.co_argcount)
print(F.__code__.co_nlocals , F.__code__.co_varnames)
print(F.__code__.co_stacksize)
print(F.__code__.co_flags)
print(F.__code__.co_names)
print(F.__code__.co_consts)

输出:
2
5 ('a', 'b', 'k', 'w', 'p')
3
67
('c' ,)
(None, 10, 1, 'two'. 3, (1, 'two', 3))

传递给此函数的参数有两个(“a”、“b”)。
此函数有两个参数(“a”、“b”)和三个局部变量(“k”、“w”、“p”)。
分解函数字节码,我们得到:
3         0 LOAD_FAST                0 (a)             #stack:  ["a"] 
3 LOAD_GLOBAL 0 (c) #stack: ["a","c"]
6 BINARY_MULTIPLY #stack: [result of a*c]
7 STORE_FAST 2 (k) #stack: []

4 10 LOAD_CONST 1 (10) #stack: [10]
13 STORE_FAST 3 (w) #stack: []

5 16 LOAD_CONST 5 ((1, 'two', 3)) #stack: [(1,"two",3)]
19 STORE_FAST 4 (p) #stack: []
22 LOAD_CONST 0 (None) #stack: [None]
25 RETURN_VALUE #stack: []

正如您可以注意到的,Chile执行函数时,堆栈中的元素永远不会超过三个(在本例中,tuple算作其长度)。
标志的值是dec 67=bin 1000011=bin 1000000+10+1=dec 64+2+1,所以我们理解
代码被优化(因为大多数自动生成的代码是这样的)
在执行函数字节码本地命名空间更改时
64?实际上我不知道它的意思是什么
函数中使用的唯一全局名称是“c”,它以co-u名称存储。
我们使用的每个显式文本都存储在co-consts中:
none是函数的返回值
我们明确地把数字10赋给w
我们明确地将(1,'2',3)分配给P
如果元组是常量,则该元组的每个元素都是常量,因此1,“2”,3是常量
––––––––––-
第二个示例
ModuleVar="hi"

def F():
FunctionVar=106
UnusedVar=ModuleVar

def G():
return (FunctionVar,ModuleVar)

print(G.__code__.co_freevars)
print(G.__code__.co_names)

F()
print(F.__code__.co_cellvars)
print(F.__code__.co_freevars)
print(F.__code__.co_names)

输出:
('FunctionVar',)
('ModuleVar',)
('FunctionVar',)
()
('print', '__code__', 'co_freevars', 'co_names', 'ModuleVar')

输出的含义如下:
第一行和第二行在执行f时打印,因此它们显示g代码的co-freevars和co-u名称:
“functionvar”位于f函数的命名空间中,其中创建了g,
“modulevar”是一个模块变量,因此它被视为全局变量。
以下三行是关于f code的co-cellvars、co-freevars和co-names属性:
“functionvar”在g嵌套函数中被引用,因此它被标记为cellvar,
“modulevar”位于创建f的命名空间中,但它是一个模块变量,
因此,它没有标记为freevar,但可以在全局名称中找到。
此外,内置函数print以名称和f中使用的所有属性名称进行标记。
––––––––––-
第三个示例
这是一个工作代码对象初始化,
这是没有用的,但是你可以用这个函数做你想做的任何事情。
MyCode= CodeType(
0,
0,
0,
3,
64,
bytes([101, 0, 0, #Load print function
101, 1, 0, #Load name 'a'
101, 2, 0, #Load name 'b'
23, #Take first two stack elements and store their sum
131, 1, 0, #Call first element in the stack with one positional argument
1, #Pop top of stack
101, 0, 0, #Load print function
101, 1, 0, #Load name 'a'
101, 2, 0, #Load name 'b'
20, #Take first two stack elements and store their product
131, 1, 0, #Call first element in the stack with one positional argument
1, #Pop top of stack
100, 0, 0, #Load constant None
83]), #Return top of stack
(None,),
('print', 'a', 'b'),
(),
'PersonalCodeObject',
'MyCode',
1,
bytes([14,1]),
(),
() )

a=2
b=3
exec(MyCode) # code prints the sum and the product of "a" and "b"

输出:
5
6

关于python - 如何在python中创建代码对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16064409/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com