gpt4 book ai didi

python - Python 中 compile() 的可逆版本

转载 作者:太空宇宙 更新时间:2023-11-03 12:43:10 25 4
gpt4 key购买 nike

我正在尝试在 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”不会)。

这是我尝试过但不起作用的方法:

  • 为编译返回的代码对象设置一个属性。您不能在代码对象上设置自定义属性。
  • 子类化代码以便我可以添加属性。代码不能被子类化。
  • 设置一个 WeakKeyDictionary 映射代码对象到原始字符串。代码对象不能被弱引用。

这是有效的方法,但有问题:

  • 将文件名的原始代码字符串传递给 compile()。但是,我失去了实际保留文件名的能力,而我也想这样做。
  • 保留将代码对象映射到字符串的真实字典。这会泄漏内存,但由于编译很少见,所以对于我当前的用例来说是可以接受的。如果必须的话,我可能可以定期通过 gc.get_referrers 运行 key 并杀死死掉的 key 。

最佳答案

这是一个奇怪的问题,我最初的 react 是你最好完全做一些其他事情来完成你想做的任何事情。但这仍然是一个有趣的问题,所以这是我的破解方法:我将原始代码源设为代码对象的未使用常量。

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)'

关于python - Python 中 compile() 的可逆版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/718769/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com