Python:如何将参数传递给函数的__code__?

Tur*_*ion 24 python eval function exec parameter-passing

以下作品:

def spam():
    print "spam"
exec(spam.__code__)
Run Code Online (Sandbox Code Playgroud)

垃圾邮件

但如果spam需要参数呢?

def spam(eggs):
    print "spam and", eggs
exec(spam.__code__)
Run Code Online (Sandbox Code Playgroud)

TypeError:spam()只需1个参数(给定0)

鉴于,我无法访问函数本身,只能访问代码对象,如何在执行代码对象时将参数传递给代码对象?是否可以使用eval?

编辑:由于大多数读者往往不相信这有用,请参阅以下用例:

我想将小Python函数保存到文件中,以便可以从另一台计算机中调用它们.(这里不用说这个用例严格限制了可能的功能.)pickle函数对象本身不起作用,因为这只保存了定义函数的名称和模块.相反,我可以腌制__code__功能.当我再次取消它时,当然对函数的引用消失了,这就是我无法调用该函数的原因.我只是在运行时没有它.

另一个用例:

我在一个文件中处理几个函数,计算一些数据并将其存储在硬盘上.计算会耗费大量时间,所以我不想每次都执行这些函数,但只有在函数的实现发生变化时才会执行.

我有一个版本的运行整个模块而不是一个功能.它通过查看实现模块的文件的修改时间来工作.但是如果我有许多我不想在单个文件中分离的函数,那么这不是一个选项.

Gus*_*son 15

我完全反对__code__的使用.

虽然我是一个好奇的人,这是理论上可以做的事情:

code # This is your code object that you want to execute

def new_func(eggs): pass
new_func.__code__ = code
new_func('eggs')
Run Code Online (Sandbox Code Playgroud)

再一次,我永远不想看到这个用过.您可能希望查看__import__是否要在运行时加载代码.

  • 您还可以使用函数类型构造函数.例如`new_func = type(lambda:0)(code,globals())`这有点不那么hacky.然后,您可以编写一个函数来从代码对象构造包装器函数并调用生成的函数. (2认同)
  • 这是一个进步.为了提高解决方案的可读性,我建议使用`types.FunctionType`而不是`type(lambda:0)`. (2认同)

ken*_*ytm 10

可以更改的功能带任何参数?然后从您可以提供的locals/globals中查找变量exec:

>>> def spam():
...   print "spam and", eggs
... 
>>> exec(spam.__code__, {'eggs':'pasta'})
spam and pasta
Run Code Online (Sandbox Code Playgroud)

(为什么不将整个函数作为字符串发送?Pickle "def spam(eggs): print 'spam and', eggs",以及exec另一方的字符串(经过验证).)


jon*_*esy 6

我认为在您的大型应用程序中可能存在一些设计注意事项,这些注意事项可能会使您不关心此问题,例如可能将一些"已知良好且有效"的函数集合作为执行代理知道的模块或其他内容进行分发.

也就是说,一个hacky解决方案是:

>>> def spam(eggs):
...     print "spam and %s" % eggs
...     
... 
>>> spam('bacon')
spam and bacon
>>> def util():
...     pass
...     
... 
>>> util.__code__ = spam.__code__
>>> util('bacon')
spam and bacon
>>> 
Run Code Online (Sandbox Code Playgroud)


Jim*_*ski 5

代码对象是函数的一部分,所以上面好几个答案建议创建一个虚拟功能和更换其__code__与你的codeObject.这是避免制作和丢弃新内容的另一种方法__code__:

import new
newFunction = new.function(codeObject, globals())
Run Code Online (Sandbox Code Playgroud)

(在Python 2.7中测试,在哪里spam.__code__命名spam.func_code.)