生成evalable 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()来测试的有效性,采取下面的一个例如断言代码字符串:

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

我的问题是:

  1. 如何生成的代码串我以高于瓦尔想?
  2. 如何枚举对于上述测试逻辑可能性(A,B,C) 例如:

    "f1(A)>200 and f1(B)>200 and f1(C)>200"
    "f1(A)<300 and f2(B)=200 or f3(C)>200"
  3. 是有可能取代的功能的名称的列表条目时生成的代码?

    "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语法)做什么:

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

...

在这种方法中,我只是通过更换骗vars_与('A','B','C')。 这旁边,我认为它应该工作。



如果不通过硬编码的喜欢我的作弊方式vars_列表和funcs_名字,你可以从全局字典像这样的变量名:

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

这相当于服用外/笛卡尔积,“求和”跨越“变种”维,并散布那些与逻辑运算的外积。 您可以使用itertools.product或者只是正常的列表理解。 以下将任意数量的变量,函数,比较器,逻辑运算符和数值阈值工作。 它也易于扩展,如果你选择,使更多复杂的表达式

#!/usr/bin/python3

from pprint import pprint as pp
from itertools import *

VARS = 'XYZ'
FUNCS = range(2)
COMPARE = '><='
LOGIC = ['and', 'or']
NUMS = [200, 300]

def listJoin(iter):
return sum(map(list,iter), [])

terms = [
[
'func[{func}]({var}){compare}{num}'.format(func=func, var=var, compare=compare, num=num)
for var in VARS
]
for func in FUNCS
for compare in COMPARE
for num in NUMS
]

def intersperse(iter, joiners):
iter = list(iter)
for tokens in product(*(joiners for _ in iter[:-1])):
yield ' '.join(listJoin(zip(iter,tokens))+[iter[-1]])

formulas = listJoin(intersperse(t, LOGIC) for t in terms)

pp(formulas)

结果:

['func[0](X)>200 and func[0](Y)>200 and func[0](Z)>200',
'func[0](X)>200 and func[0](Y)>200 or func[0](Z)>200',
'func[0](X)>200 or func[0](Y)>200 and func[0](Z)>200',
'func[0](X)>200 or func[0](Y)>200 or func[0](Z)>200',
'func[0](X)>300 and func[0](Y)>300 and func[0](Z)>300',
'func[0](X)>300 and func[0](Y)>300 or func[0](Z)>300',
'func[0](X)>300 or func[0](Y)>300 and func[0](Z)>300',
'func[0](X)>300 or func[0](Y)>300 or func[0](Z)>300',
'func[0](X)<200 and func[0](Y)<200 and func[0](Z)<200',
'func[0](X)<200 and func[0](Y)<200 or func[0](Z)<200',
'func[0](X)<200 or func[0](Y)<200 and func[0](Z)<200',
'func[0](X)<200 or func[0](Y)<200 or func[0](Z)<200',
'func[0](X)<300 and func[0](Y)<300 and func[0](Z)<300',
'func[0](X)<300 and func[0](Y)<300 or func[0](Z)<300',
'func[0](X)<300 or func[0](Y)<300 and func[0](Z)<300',
'func[0](X)<300 or func[0](Y)<300 or func[0](Z)<300',
'func[0](X)=200 and func[0](Y)=200 and func[0](Z)=200',
'func[0](X)=200 and func[0](Y)=200 or func[0](Z)=200',
'func[0](X)=200 or func[0](Y)=200 and func[0](Z)=200',
'func[0](X)=200 or func[0](Y)=200 or func[0](Z)=200',
'func[0](X)=300 and func[0](Y)=300 and func[0](Z)=300',
'func[0](X)=300 and func[0](Y)=300 or func[0](Z)=300',
'func[0](X)=300 or func[0](Y)=300 and func[0](Z)=300',
'func[0](X)=300 or func[0](Y)=300 or func[0](Z)=300',
'func[1](X)>200 and func[1](Y)>200 and func[1](Z)>200',
'func[1](X)>200 and func[1](Y)>200 or func[1](Z)>200',
'func[1](X)>200 or func[1](Y)>200 and func[1](Z)>200',
'func[1](X)>200 or func[1](Y)>200 or func[1](Z)>200',
'func[1](X)>300 and func[1](Y)>300 and func[1](Z)>300',
'func[1](X)>300 and func[1](Y)>300 or func[1](Z)>300',
'func[1](X)>300 or func[1](Y)>300 and func[1](Z)>300',
'func[1](X)>300 or func[1](Y)>300 or func[1](Z)>300',
'func[1](X)<200 and func[1](Y)<200 and func[1](Z)<200',
'func[1](X)<200 and func[1](Y)<200 or func[1](Z)<200',
'func[1](X)<200 or func[1](Y)<200 and func[1](Z)<200',
'func[1](X)<200 or func[1](Y)<200 or func[1](Z)<200',
'func[1](X)<300 and func[1](Y)<300 and func[1](Z)<300',
'func[1](X)<300 and func[1](Y)<300 or func[1](Z)<300',
'func[1](X)<300 or func[1](Y)<300 and func[1](Z)<300',
'func[1](X)<300 or func[1](Y)<300 or func[1](Z)<300',
'func[1](X)=200 and func[1](Y)=200 and func[1](Z)=200',
'func[1](X)=200 and func[1](Y)=200 or func[1](Z)=200',
'func[1](X)=200 or func[1](Y)=200 and func[1](Z)=200',
'func[1](X)=200 or func[1](Y)=200 or func[1](Z)=200',
'func[1](X)=300 and func[1](Y)=300 and func[1](Z)=300',
'func[1](X)=300 and func[1](Y)=300 or func[1](Z)=300',
'func[1](X)=300 or func[1](Y)=300 and func[1](Z)=300',
'func[1](X)=300 or func[1](Y)=300 or func[1](Z)=300']

首先,我会说的eval是一个坏idea.There始终是另一种方式来做到这一点开始。

回答你的问题:

问题1:

功能名称,

你可以使用f.func_name。

变量名,

没有那么简单,但这应该工作,

import gc, sys

def find_names(obj):
frame = sys._getframe()
for frame in iter(lambda: frame.f_back, None):
frame.f_locals
result = []
for referrer in gc.get_referrers(obj):
if isinstance(referrer, dict):
for k, v in referrer.iteritems():
if v is obj:
result.append(k)
return result

a = 97
print find_names(a)[0]

如果返回错误的名字,因为它们的价值将等于不要紧。

操作者和vol_limit容易产生。

第二个问题。

没有明显的解决方案了心思。 通过所有这些迭代?

第三个问题。

是的,它是可能的。 退房装饰。

分类:蟒蛇 时间:2015-03-16 人气:14
本文关键词: 蟒蛇,EVAL
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 0.289 (s). 10 q(s)