python语言的执行过程_Python:在执行过程中分析复杂的语句

该博客讨论如何在Python运行时获取复杂if语句中导致条件为真的部分。通过创建一个`Evaluator`类,利用Python的`eval`函数和一个追踪字典来记录评估过程中涉及的变量,可以推断出哪个子表达式导致了结果。这种方法适用于分类算法,以确定哪些属性对类别划分最重要,即使语句嵌套且包含大量逻辑运算符。
摘要由CSDN通过智能技术生成

我想知道是否有任何方法可以在执行期间获取有关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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值