生成可评估的python代码:析取范式的所有功能组合 [英] Generating evalable python code: all combinations of functions in disjunctive normal form

查看:156
本文介绍了生成可评估的python代码:析取范式的所有功能组合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(A,B,C) = (100, 200, 300)

def f1(p): return p+50 
def f2(p): return p*1.5 
def f3(p): return p*p 

vars_ = (A,B,C)
funcs_ = [f1, f2, f3]
logic_ = ["and","or"]
vol_lmt_ = [200, 300]
op_ = [">","<","="] 

我想为eval()生成断言代码字符串以测试有效性,以下面的示例为例:

I want generate the assert code string for eval() to test the validity, take below one for example:

"f1(A)>200 and f1(B)>200 and f1(C)>200"                             # True
 -^-------------^-------------^------------: funcs_
 ----^-------------^-------------^---------: vars_
 ------^-------------^-------------^-------: op_
 --------^-------------^-------------^-----: vol_lmt_        
 ------------^-------------^---------------: logic_

我的问题是:

  1. 如何根据上述变量生成我想要的代码字符串?

  1. how to generate the code string I wanted based on those vars above?

如何列举以上(A,B,C)的所有测试逻辑可能性?例如:

how to enumerate all test logic possibility for above (A,B,C)? For example:

"f1(A)>200 and f1(B)>200 and f1(C)>200"
"f1(A)<300 and f2(B)=200 or f3(C)>200"

在生成代码时是否可以将函数名称替换为列表项?

is it possible to replace the the name of function to the list entry when generate the code?

"f(A)>200 and f1(B)>200 and f1(C)>200"

收件人

"funcs_[0](A)>200 and funcs_[0](B)>200 and funcs_[0](C)>200"

推荐答案

也许这可以总结您想要做的事情(使用python2语法):

Maybe this can summaries what you are trying to do (using python2 syntax):

import itertools

arguments = ('A', 'B', 'C', 'D')
funcs_ = [f1, f2, f3, f4]
logic_ = ["and","or"]
op_ = [">","<","="]
vol_lmt_ = [200, 300]

num_func = len(funcs_)

assert num_func == len(arguments), ("The number of argument should be the same as "
                                    "the number of function.")

operands = itertools.product(["funcs_[%d]" % i for i in range(num_func)],
                             arguments,
                             op_,
                             vol_lmt_)

def comp(operands):
    templ = "{func}({arg}){op}{val}"
    for operand in operands:
        yield templ.format(func=operand[0], arg=operand[1],
                           op=operand[2], val=operand[3])

new_operands = map(comp, itertools.tee(operands, num_func))

# construct the argument to pass to itertools.product.
args = []
for operand in new_operands:
    args.append(operand)
    args.append(logic_)

args.pop() # Remove the last logic operator.

res = itertools.product(*args)

print " ".join(res.next())
# funcs_[0](A)>200 and funcs_[0](A)>200 and funcs_[0](A)>200 and funcs_[0](A)>200

...

在这种方法中,我只是用('A','B','C')替换了vars_而作弊.除此之外,我认为它应该可以工作.

In this method i just cheated by replacing vars_ with ('A', 'B', 'C'). beside that i think it should work.

如果您不喜欢通过硬编码vars_列表和funcs_名称来欺骗我的作弊方式,则可以从

If you don't like my way of cheating by hard coding the the vars_ list and the funcs_ name you can get the name of your variable from the globals dictionary something like this:

def get_name(obj):
    """Get the name of an object (variable) from the globals dict.

    Argument:
       - obj : The variable that we want to get the name of. 

    Return:
       - A string representing the name of the object if it was found else return None.

    """

    for name, value in globals().items():
         if value is obj:
             return name

这篇关于生成可评估的python代码:析取范式的所有功能组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆