首先,是的,我知道这不是好习惯。这只是一个实验,而不是实际的计划代码。
问题: 我有一个功能
def foo:
print("hi there")
def foo2:
#Any stack/recompiling manipulation goes here
def main:
foo2()
foo()
在运行时是否可以通过foo2()处理foo()的定义?
我一直在努力尝试更改帧中的变量,但是大多数都是只读的(保存f_local)。
答案 0 :(得分:2)
如果您对python中的字节码级别的东西感兴趣,请允许我介绍dis
,compile
和CodeType
请勿在生产代码中执行任何此操作
您可以将compile
python代码(作为字符串)放入Code对象,然后可以覆盖函数的__code__
属性
def foo():
print('hi there')
code_stuff = compile("print('this is hacked in')", "dummy file", "exec")
foo.__code__ = code_stuff
foo() #prints "this is hacked in"
如果您要修改多于无输入无输出功能,请查看types.CodeType
构造函数:
>>> import types
>>> help(types.CodeType)
Help on class code in module builtins:
class code(object)
| code(argcount, kwonlyargcount, nlocals, stacksize, flags, codestring,
| constants, names, varnames, filename, name, firstlineno,
| lnotab[, freevars[, cellvars]])
|
| Create a code object. Not for the faint of heart.
| ...
与编写汇编代码很像,这涉及到存在段错误,使python解释器崩溃或更糟的风险。您知道唯一的文档是Not for the faint of heart.
时,开发人员并不打算直接使用它。
如果要查看实际执行的字节码,可以使用dis
。这是“拆卸”的缩写
def foo():
print('hi there')
import dis
dis.dis(foo)
这很有趣,看看python代码实际上是如何执行的。
我不确定您要对堆栈进行什么操作,但我可以肯定它是什么,python的开发人员已确保这并不容易,因为这不是您应该在python中接触的东西。这些类型仅出于自省的原因而存在于python中(例如,通过检查函数的调用签名来查看函数的参数在运行时是什么)
答案 1 :(得分:1)
如果您想操纵foo
的定义,可以像使用其他任何全局变量一样使用foo
语句和{{1 }}:
global
将=
放在def foo():
print('hi there')
def foo2():
global foo
def replacement_foo():
print('hi from over here')
foo = replacement_foo
def main():
foo2()
foo()
main()
内而不是定义def foo(): ...
然后进行分配也很安全,但这是officially not permitted,即使实现未强制执行。
在注释中,您似乎对以某种方式操纵堆栈中的foo2
非常感兴趣。 replacement_foo
的定义不在堆栈上,并且在执行foo
期间堆栈上没有对foo
的调用,因此堆栈是错误的查找位置。 / p>
此外,Python的大多数堆栈检查都是只读的。即使您要重新分配函数的代码对象,它也不会更改已在堆栈中的调用的代码。您不能更改foo
的代码对象以使其不调用foo
(尽管您可以更改main
的代码对象,并且在{{1} }调用foo
)。