如何在runtim期间修改/重新编译已定义的函数

2024-09-24 02:22:58 发布

您现在位置:Python中文网/ 问答频道 /正文

首先,是的,我知道这是不好的做法。这只是一个实验,而不是实际的计划代码。你知道吗

问题是: 我有一个函数

def foo:
    print("hi there")

def foo2:
    #Any stack/recompiling manipulation goes here

def main:
    foo2()
    foo()

有没有办法在运行时从foo2()操作foo()的定义?你知道吗

我一直在尝试修改帧中的变量,但大多数都是只读的(保存f\u local)。你知道吗


Tags: 函数代码herefoostackdefanyhi
2条回答

如果您想操作foo的定义,可以直接用global语句和=来重新定义foo与分配任何其他全局变量的方式非常相似:

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(): ...内部foo2而不是定义replacement_foo然后赋值也可能是安全的,但这就是officially not permitted,即使实现没有强制执行它。你知道吗


在注释中,您似乎对通过堆栈操纵foo非常感兴趣。foo的定义不在堆栈上,在执行foo期间,堆栈上没有对foo的调用,因此堆栈是错误的查找位置。你知道吗

另外,Python的大多数堆栈检查都是只读的。即使要重新分配函数的code对象,它也不会更改堆栈上已有的调用代码。您不能更改main的代码对象,使其不调用foo(尽管您可以更改foo的代码对象,这将在main调用foo时生效)。你知道吗

如果您对python中的字节码级内容感兴趣,让我来介绍discompileCodeType

不要在生产代码中执行这些操作

您可以将compilepython代码(作为字符串)转换为code对象,然后该对象可以重写functions __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"

如果要修改多个no inputs no outputs函数,请查看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.
 |  ...

这与编写汇编代码很相似,可能会导致seg错误、python解释器崩溃甚至更糟。你知道当唯一的文档是Not for the faint of heart.时,开发人员并不打算直接使用它。你知道吗

如果您想查看实际执行的字节码,可以使用dis。是“拆卸”的缩写

def foo():
    print('hi there')

import dis
dis.dis(foo)

看看python代码实际上是如何执行的,这很有趣。你知道吗

我不确定您到底想用这个堆栈做什么,但我相当肯定它到底是什么,python的开发人员已经确保它不容易,因为这在python中不是您应该接触的东西。这些类型只存在于python中是为了内省(比如通过检查函数的调用签名来查看函数在运行时的参数)

相关问题 更多 >