2015-09-06 106 views
0

有没有在Python 3.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: <module>() takes 0 positional arguments but 2 were given

在为compile()它writen与它编译的代码可以与eval()exec()运行的文档。有没有办法编译一个函数,并通过没有eval()和exec()的函数对象来调用它?

+2

我想知道问题是什么,需要自修改代码作为解决方案? –

+0

@Roland我试图使用一些仅在运行时才知道的信息(速度增强)。 –

+0

也许你应该发表一个问题如何处理这个问题,但有更多的细节。可能有更好的方法。我假设你已经对代码进行了剖析,以显示程序大部分时间花在哪里? –

回答

2

你可能有过exec()eval()运行它只是执行功能定义。您可以将它传递给一个单独的环境,您必须自己从中提取该函数(正如用户HelloWorld正确表示的那样,Python不能“猜测”您的意思)。

回到你的例子,在这里我首先创建一个空的环境environment,然后将编译的代码和字典传递给exec以评估定义。使用types库中的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") 
+0

几乎是魔法。谢谢! –

1

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? 

正如你从这个例子中看到的,我们编译了一个不能简单地附加到类的整个范围。你需要做的是从代码对象中提取meth1函数,然后使用它。

你应该看看下面有关代码对象的漂亮文章,它给你一些很好的见解。

http://late.am/post/2012/03/26/exploring-python-code-objects.html

+0

感谢您的链接,我会检查它。 –