在Python中反向执行函数
我有一个函数,看起来像这样:在Python中反向执行函数,python,function,Python,Function,我有一个函数,看起来像这样: def f(): call_some_function_A() call_some_function_B() [...] call_some_function_Z() 我希望函数以相反的方式执行;也就是说,执行必须如下所示: def f'(): call_some_function_Z() [...] call_some_function_B() call_some_function_A() (f在逻辑上总是可以反转的;即,没有变
def f():
call_some_function_A()
call_some_function_B()
[...]
call_some_function_Z()
我希望函数以相反的方式执行;也就是说,执行必须如下所示:
def f'():
call_some_function_Z()
[...]
call_some_function_B()
call_some_function_A()
(f
在逻辑上总是可以反转的;即,没有变量声明或类似的东西)
我怎样才能做到这一点
我不能只写一个函数f'
,它从f
反向调用语句,因为我不想每次f
更改时都要更新f'
我也不能修改f
(请不要告诉我我不应该尝试这样做,或者重新设计我的代码,或者诸如此类的事情-这是不可能的。)如果您的f()
完全由这些函数调用组成,您可以将其重制为一个列表:
functions = [
call_some_function_A,
call_some_function_B,
# [...]
call_some_function_Z,
]
然后使用它按(相反)顺序调用函数
请不要这样做。
如果
f()
完全由以下函数调用组成:
def f():
call_some_function_A()
call_some_function_B()
# [...]
call_some_function_Z()
…您可以侵入它并获取它引用的所有名称:
names = f.__code__.co_names
# ('call_some_function_A', 'call_some_function_B', 'call_some_function_Z')
但是您仍然需要得到相应的函数
如果功能在其他模块或类似模块中,只需执行以下操作:
functions = [getattr(some_module, name) for name in names]
如果函数与全局函数在同一文件中定义,请执行以下操作:
functions = [globals()[name] for name in names]
# [<function __main__.call_some_function_A>, <function __main__.call_some_function_B>, <function __main__.call_some_function_Z>]
或者,您可以获取函数的源代码,解析它,反转抽象语法树,编译它,执行它。。。你将拥有相反的功能
让我们考虑这个例子:
def f():
call_some_function_A()
if whatever:
call_some_function_B()
call_some_function_C()
call_some_function_D()
导入检查
导入ast
原始f=f
source=inspect.getsource(f)
tree=ast.parse(源代码)
#树是一个模块,其主体由1个FunctionDef组成
#body[0]是一个FunctionDef,其body由expr组成
tree.body[0]。body.reverse()
#顶级表达式将被反转
#将修改后的语法树作为模块编译为代码对象并执行它
exec(编译(树,,'exec'))
#f将被覆盖,因为函数名保持不变
#现在f等于:
#def():
#调用一些函数
#如果测试:
#调用一些函数
#调用一些函数
#调用某个函数
f_uuf=f
f=原始的
所以,是的,这个方法好一点。甚至可以递归地反转所有的
主体
s,并实现..B
和..C
的反转,但即使引入最简单的逻辑代码,您也会遇到糟糕的问题。我将这个小函数拼凑在一起,该函数假定该函数是一个简单的单行语句列表。它使用exec,这是eval的另一种形式,因此很难编译代码,但如果您可以在这里使用经过评估的代码,它就是:
import inspect
# sample function that will be reversed
def f():
print "first statement"
print "2nd statement"
print "last statement"
def makeReversedFunctionSrc(newName, f):
src = inspect.getsource(f)
srcLines = src.split("\n")
srcLines = srcLines[1:] # get rid of the old function definition
srcLines.reverse() # reverse function body
# hack together new function definition with reversed lines
newSrc = "def " + newName + "():\n"
for line in srcLines:
if line.strip() != "":
newSrc += line + "\n"
return newSrc
# get the code as a string
reverseCode = makeReversedFunctionSrc("reversedF", f)
# execute the string as if it was python (I heard thats evil as in eval)
exec(reverseCode)
# now lets call our new function
reversedF()
+我本来打算做那样的事!一个函数列表就是我想要的。干得好。谢谢你的回答!这可能有效,但我无法修改
f
。
def f():
call_some_function_A()
if whatever:
call_some_function_B()
call_some_function_C()
call_some_function_D()
import inspect
import ast
original_f = f
source = inspect.getsource(f)
tree = ast.parse(source)
# tree is a Module, with body consisting of 1 FunctionDef
# tree.body[0] is a FunctionDef, with body consisting of Exprs
tree.body[0].body.reverse()
# top level expressions will be reversed
# compile the modified syntax tree to a code object as a module and execute it
exec(compile(tree, '<unknown>', 'exec'))
# f will be overwritten because the function name stays the same
# now f will be equivalent to:
# def f():
# call_some_function_D()
# if test:
# call_some_function_B()
# call_some_function_C()
# call_some_function_A()
f_ = f
f = original_f
import inspect
# sample function that will be reversed
def f():
print "first statement"
print "2nd statement"
print "last statement"
def makeReversedFunctionSrc(newName, f):
src = inspect.getsource(f)
srcLines = src.split("\n")
srcLines = srcLines[1:] # get rid of the old function definition
srcLines.reverse() # reverse function body
# hack together new function definition with reversed lines
newSrc = "def " + newName + "():\n"
for line in srcLines:
if line.strip() != "":
newSrc += line + "\n"
return newSrc
# get the code as a string
reverseCode = makeReversedFunctionSrc("reversedF", f)
# execute the string as if it was python (I heard thats evil as in eval)
exec(reverseCode)
# now lets call our new function
reversedF()