我正在尝试在Python中创建一个与compile()相同的函数,但也让我得到原始字符串。为了消除歧义,我们将这两个函数称为comp()和decomp()。也就是说,
a = comp("2 * (3 + x)", "", "eval")
eval(a, dict(x=3)) # => 12
decomp(a) # => "2 * (3 + x)"
返回的字符串不必是相同的(“2 *(3 + x)”是可以接受的),但它必须基本相同(“2 * x + 6”不会是。)
以下是我尝试无法工作的内容:
以下是有效的问题:
答案 0 :(得分:6)
这是一个奇怪的问题,我最初的反应是,你可能最好做一些其他事情来完成你想做的任何事情。但它仍然是一个有趣的问题,所以这是我对它的破解:我使原始代码源成为代码对象的未使用常量。
import types
def comp(source, *args, **kwargs):
"""Compile the source string; takes the same arguments as builtin compile().
Modifies the resulting code object so that the original source can be
recovered with decomp()."""
c = compile(source, *args, **kwargs)
return types.CodeType(c.co_argcount, c.co_nlocals, c.co_stacksize,
c.co_flags, c.co_code, c.co_consts + (source,), c.co_names,
c.co_varnames, c.co_filename, c.co_name, c.co_firstlineno,
c.co_lnotab, c.co_freevars, c.co_cellvars)
def decomp(code_object):
return code_object.co_consts[-1]
>>> a = comp('2 * (3 + x)', '', 'eval')
>>> eval(a, dict(x=3))
12
>>> decomp(a)
'2 * (3 + x)'
答案 1 :(得分:4)
我的方法是将代码对象包装在另一个对象中。像这样:
class CodeObjectEnhanced(object):
def __init__(self, *args):
self.compiled = compile(*args)
self.original = args[0]
def comp(*args):
return CodeObjectEnhanced(*args)
然后,只要您需要代码对象本身,就可以使用a.compiled,只要您需要原始代码,就可以使用原始代码。可能有一种方法可以让eval将新类视为普通代码对象,将函数重定向到调用eval(self.compiled)。
这样做的一个优点是原始字符串与代码对象同时被删除。但是,你这样做,我认为存储原始字符串可能是最好的方法,因为你最终得到你使用的确切字符串,而不仅仅是近似值。