Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在运行时修改/重新编译已定义的函数_Python_Python 3.x - Fatal编程技术网

Python 如何在运行时修改/重新编译已定义的函数

Python 如何在运行时修改/重新编译已定义的函数,python,python-3.x,Python,Python 3.x,首先,是的,我知道这不是一个好的做法。这只是一个实验,不是实际的计划代码 问题是: 我有一个函数 def foo: print("hi there") def foo2: #Any stack/recompiling manipulation goes here def main: foo2() foo() 有没有办法在运行时从foo2()操作foo()的定义 我一直在尝试更改帧中的变量,但大多数都是只读的(保存f_local)。如果您想操作foo的定义,可

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

问题是: 我有一个函数

def foo:
    print("hi there")

def foo2:
    #Any stack/recompiling manipulation goes here

def main:
    foo2()
    foo()
有没有办法在运行时从foo2()操作foo()的定义


我一直在尝试更改帧中的变量,但大多数都是只读的(保存f_local)。

如果您想操作
foo
的定义,可以直接重新定义
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()
foo2
中定义
def foo():…
而不是定义
replacement\u foo
然后分配,这可能也是安全的,但即使实现没有强制执行它


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


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

如果要操作
foo
的定义,重新定义
foo
非常简单,就像分配任何其他全局变量一样,使用
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()
foo2
中定义
def foo():…
而不是定义
replacement\u foo
然后分配,这可能也是安全的,但即使实现没有强制执行它


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


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

如果您对python中的字节码级内容感兴趣,请允许我介绍
dis
编译
代码类型

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

您可以
python代码(作为字符串)编译成一个code对象,然后该对象可以重写functions
\uuuuuuuuuuuuuuuuu
属性

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.
 |  ...
这就像编写汇编代码一样,可能会导致seg故障、python解释器崩溃或更糟。你知道什么时候唯一的文档是
不是为胆小的人准备的。
开发人员并不打算直接使用它

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

看看python代码实际上是如何执行的,这很有趣


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

如果您对python中的字节码级内容感兴趣,那么让我介绍一下
dis
compile
CodeType

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

您可以
python代码(作为字符串)编译成一个code对象,然后该对象可以重写functions
\uuuuuuuuuuuuuuuuu
属性

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.
 |  ...
这就像编写汇编代码一样,可能会导致seg故障、python解释器崩溃或更糟。你知道什么时候唯一的文档是
不是为胆小的人准备的。
开发人员并不打算直接使用它

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

看看python代码实际上是如何执行的,这很有趣


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

这不会修改原始函数
foo
,但是,它通过重新指定全局名称
foo
,将其替换为完全无关的函数。(这可能是OP想要的,也可能不是。)这是真的,虽然这确实有帮助,但我想知道是否有可能替换堆栈中的东西。例如,修改执行流中的当前行/位置,更改main的底层字节码等。@JonathanBurk:
foo
foo2
运行时不在堆栈上,所以我不确定您为什么要谈论堆栈。你的目标是摆弄