我想知道是否有任何方法可以在执行期间获取有关python语句解释的一些元信息.
假设这是一个复杂的语句,其中某些语句与或相连(A,B,…是布尔函数)
if A or B and ((C or D and E) or F) or G and H:
我想知道该语句的哪一部分导致该语句的评估结果为True,因此我可以利用这些知识来做一些事情.在此示例中,将有3个可能的候选者:
A
B and ((C or D and E) or F)
G and H
在第二种情况下,我想知道是(C或D和E)还是F评估为True,依此类推…
有什么办法不解析该语句?我可以以某种方式连接到解释器,还是可以以尚未发现的方式使用检查模块?我不想调试,这实际上是要知道此Or-chain的哪一部分在运行时触发了该语句.
编辑-其他信息:我要在其中使用的应用程序类型是一种分类算法,该算法根据对象的属性输入对象并为该对象输出特定类别.我需要知道哪些属性对类别至关重要.
您可能会猜到,上面的复杂语句来自分类算法.该算法的代码是从形式化的伪代码生成的,包含大约3,000个嵌套的if-elif语句,这些语句以分层方式确定类别,例如
if obj.attr1 < 23 and (is_something(obj.attr10) or eats_spam_for_breakfast(obj)):
return 'Category1'
elif obj.attr3 == 'Welcome Home' or count_something(obj) >= 2:
return 'Category2a'
elif ...
因此,除了类别本身之外,我还需要标记对该类别具有决定性的属性,因此,如果我删除所有其他属性,则该对象仍将分配给同一类别(由于语句中的ors).语句可能很长,最多1000个字符,并且嵌套得很深.每个对象最多可以具有200个属性.
非常感谢你的帮助!
编辑2:最近两周没有时间.感谢您提供此解决方案,它可以正常工作!
解决方法:
您可以重新编码原始代码:
if A or B and ((C or D and E) or F) or G and H:
如,说:
e = Evaluator()
if e('A or B and ((C or D and E) or F) or G and H'):
…?如果是这样,那就有希望!-).在__call__上,Evaluator类将编译其字符串参数,然后使用(对全局变量为空的真实dict和对本地变量的伪dict)评估结果,实际上将值查找委托给其调用方的本地变量和全局变量(仅需要一点黑魔法,但是还算不错;-)并记下它查找的名字.给定Python和和或的短路行为,您可以从实际查找的实际名称集合中推断出一个名称,该名称确定了表达式(或每个子表达式)的真值-在X或Y或Z中,第一个真值(如果有)将是最后一个被查询的值,在X,Y和Z中,第一个假值将是.
这会有所帮助吗?如果是的话,并且如果您需要编码方面的帮助,我将很乐于对此进行扩展,但是首先,我想确认一下,获取Evaluator的代码确实可以解决您试图解决的任何问题地址!-)
编辑:因此,这里是实现评估器并举例说明其用法的编码:
import inspect
import random
class TracingDict(object):
def __init__(self, loc, glob):
self.loc = loc
self.glob = glob
self.vars = []
def __getitem__(self, name):
try: v = self.loc[name]
except KeyError: v = self.glob[name]
self.vars.append((name, v))
return v
class Evaluator(object):
def __init__(self):
f = inspect.currentframe()
f = inspect.getouterframes(f)[1][0]
self.d = TracingDict(f.f_locals, f.f_globals)
def __call__(self, expr):
return eval(expr, {}, self.d)
def f(A, B, C, D, E):
e = Evaluator()
res = e('A or B and ((C or D and E) or F) or G and H')
print 'R=%r from %s' % (res, e.d.vars)
for x in range(20):
A, B, C, D, E, F, G, H = [random.randrange(2) for x in range(8)]
f(A, B, C, D, E)
这是示例运行的输出:
R=1 from [('A', 1)]
R=1 from [('A', 1)]
R=1 from [('A', 1)]
R=1 from [('A', 0), ('B', 1), ('C', 1)]
R=1 from [('A', 1)]
R=1 from [('A', 0), ('B', 0), ('G', 1), ('H', 1)]
R=1 from [('A', 1)]
R=1 from [('A', 1)]
R=1 from [('A', 0), ('B', 1), ('C', 1)]
R=1 from [('A', 1)]
R=1 from [('A', 0), ('B', 1), ('C', 1)]
R=1 from [('A', 1)]
R=1 from [('A', 1)]
R=1 from [('A', 1)]
R=0 from [('A', 0), ('B', 0), ('G', 0)]
R=1 from [('A', 1)]
R=1 from [('A', 1)]
R=1 from [('A', 1)]
R=0 from [('A', 0), ('B', 0), ('G', 0)]
R=1 from [('A', 0), ('B', 1), ('C', 1)]
您会经常看到(大约50%的时间)A为真,这会使所有内容短路.当A为假时,B求值-当B也为假时,则G为下一个,当B为真时,则为C.
标签:interpreter,logic,python
来源: https://codeday.me/bug/20191107/2002276.html