Python 如何在运行时编译函数?

Python 如何在运行时编译函数?,python,Python,在Python3.x中,有没有一种方法可以使用标准库在运行时编译函数并通过函数对象使用它 我尝试了以下方法: class A: def meth1(self, par1): print("in A.meth1: par1 =", par1) a = A() s = '''def meth1(self, par1): print("in recompiled A.meth1: par1 = ", par1)''' a.meth1.__func__.__co

在Python3.x中,有没有一种方法可以使用标准库在运行时编译函数并通过函数对象使用它

我尝试了以下方法:

class A:    
    def meth1(self, par1):
        print("in A.meth1: par1 =", par1)

a = A()
s = '''def meth1(self, par1):
    print("in recompiled A.meth1: par1 = ", par1)'''
a.meth1.__func__.__code__ = compile( s, __file__, "exec")
a.meth1("via meth1")
但这会产生一个错误:

TypeError:
)接受0个位置参数,但提供了2个


compile()。有没有一种方法可以在没有eval()和exec()的情况下编译函数并通过函数对象调用它?

jojonas给出了一个很好的答案,这篇文章与其说是一个答案,不如说是一个附加评论

不能简单地编译字符串并替换类中的代码对象。调用
compile
后得到的是一个代码对象。例如,查看以下代码

obj = '''
def meth1(self, par1):
    print("in recompiled A.meth1: par1 = ", par1)

def meth2(self, par1):
        print("in recompiled A.meth2: par1 = ", par1)
'''
a.meth1.__func__.__code__ = compile(obj, __file__, "exec") # What should happen here?
从这个示例中可以看到,我们编译了一个不能简单地附加到类的整个范围。您需要做的是从code对象中提取
meth1
函数并使用它

您应该看看下面这篇关于代码对象的文章,这篇文章为您提供了一些很好的见解


乔乔纳斯给出了一个很好的答案,这篇文章与其说是一个答案,不如说是一篇附加评论

不能简单地编译字符串并替换类中的代码对象。调用
compile
后得到的是一个代码对象。例如,查看以下代码

obj = '''
def meth1(self, par1):
    print("in recompiled A.meth1: par1 = ", par1)

def meth2(self, par1):
        print("in recompiled A.meth2: par1 = ", par1)
'''
a.meth1.__func__.__code__ = compile(obj, __file__, "exec") # What should happen here?
从这个示例中可以看到,我们编译了一个不能简单地附加到类的整个范围。您需要做的是从code对象中提取
meth1
函数并使用它

您应该看看下面这篇关于代码对象的文章,这篇文章为您提供了一些很好的见解


您可能需要通过
exec()
eval()
运行函数定义。您可以向它传递一个单独的环境,您必须自己从中提取函数(正如用户HelloWorld正确地说的,Python无法“猜测”您指的是哪个函数)

回到您的示例,这里我首先创建一个空的环境
environment
,然后将编译好的代码和字典传递给
exec
,以评估定义。使用库中的
MethodType
类,必须将函数转换为绑定方法,并提供类或实例作为第二个参数。然后可以将绑定方法附加到原始实例

import types

class A:    
    def meth1(self, par1):
        print("in A.meth1: par1 =", par1)

a = A()
s = '''def meth1(self, par1):
    print("in recompiled A.meth1: par1 = ", par1)'''

code = compile(s, __file__, "exec")

environment = {}
exec(code, environment)
a.meth1 = types.MethodType(environment["meth1"], A)

a.meth1("via meth1")

您可能需要通过
exec()
eval()
运行它才能执行函数定义。您可以向它传递一个单独的环境,您必须自己从中提取函数(正如用户HelloWorld正确地说的,Python无法“猜测”您指的是哪个函数)

回到您的示例,这里我首先创建一个空的环境
environment
,然后将编译好的代码和字典传递给
exec
,以评估定义。使用库中的
MethodType
类,必须将函数转换为绑定方法,并提供类或实例作为第二个参数。然后可以将绑定方法附加到原始实例

import types

class A:    
    def meth1(self, par1):
        print("in A.meth1: par1 =", par1)

a = A()
s = '''def meth1(self, par1):
    print("in recompiled A.meth1: par1 = ", par1)'''

code = compile(s, __file__, "exec")

environment = {}
exec(code, environment)
a.meth1 = types.MethodType(environment["meth1"], A)

a.meth1("via meth1")

值得一提的是,我最近创建了一个
@compile\u fun
goodie,它大大简化了在函数上应用
compile
的过程。你的例子写道:

class A:
    @compile_fun
    def meth1(self, par1):
        print("in A.meth1: par1 =", par1)
您可以看到,现在无法使用IDE调试到
meth1
。请注意,这不会提高运行时性能,也不会保护您的代码不受反向工程的影响,但如果您不希望用户在调试时看到函数的内部结构,这可能会很方便。请注意,明显的缺点是它们无法帮助您调试lib,因此请小心使用


有关详细信息,请参见
makefun

关于它的价值,我最近创建了一个
@compile\u fun
goodie,它大大简化了在函数上应用
compile
的过程。你的例子写道:

class A:
    @compile_fun
    def meth1(self, par1):
        print("in A.meth1: par1 =", par1)
您可以看到,现在无法使用IDE调试到
meth1
。请注意,这不会提高运行时性能,也不会保护您的代码不受反向工程的影响,但如果您不希望用户在调试时看到函数的内部结构,这可能会很方便。请注意,明显的缺点是它们无法帮助您调试lib,因此请小心使用


有关详细信息,请参见
makefun

我想知道需要自我修改代码作为解决方案的问题是什么?@Roland我正在尝试使用一些只有在运行时才知道的信息进行优化(速度增强)。也许你应该发布一个问题,如何处理这个问题,但要提供更多详细信息。也许有更好的办法。我假设您已经分析了代码,以显示程序花费大部分时间的位置?我想知道需要自我修改代码作为解决方案的问题是什么?@Roland我试图使用一些只有在运行时才知道的信息进行优化(速度增强).也许你应该提出一个问题,如何处理这个问题,但要有更多的细节。也许有更好的办法。我假设您已经分析了代码以显示程序在哪里花费了大部分时间?谢谢链接,我会检查它。谢谢链接,我会检查它。