Python: как проверить пользовательские условия? - PullRequest
0 голосов
/ 30 октября 2010

я борюсь с тем, чтобы протестировать предопределенные условия, которые принимают параметры, предоставленные пользователем, как в примере ниже:

cond = "if ( 1 is yes and 2 is no ) or ( 1 is yes and 2 is no )"  
cond2 = "if (3 is no or 1 is no )"  
vars = []  

lst = cond.split()  
lst += cond2.split()  

for l in lst:  
   if l.isdigit():  
      if l not in vars:  
         vars.append(l)  
# ... sort 
# ... read user answers => x = no, y = no, y = yes 
# ... replace numbers with input (yes or no)

# ... finally I have 

cond = "if ( no is yes and no is no ) or ( no is yes and no is no )"
cond2 = "if (yes is no or no is no )" 

Прежде всего, это правильный подход?
Во-вторых, как мне проверить вышеуказанные условия, если True или False?

Спасибо заранее.

Ответы [ 3 ]

1 голос
/ 30 октября 2010

Используйте Языковые службы Python , чтобы проанализировать и скомпилировать строку, а затем выполнить полученный AST.

0 голосов
/ 31 октября 2010

Все ответы пользователя, взятые вместе, могут использоваться для формирования уникального двоичного числа (одно состоит только из нулей и единиц). Вы можете составить таблицу (список) для каждого условия, проиндексированного каждой из возможных комбинаций ответа в каждой позиции, для хранения значения, которое данное условие - выраженное как лямбда-функция - будет иметь для этого набора.

После того, как эти таблицы настроены, вы можете определить, выполняется ли какое-либо условие, посмотрев значение в соответствующей таблице, проиндексированное с помощью данной комбинации ответов. Ниже приведен пример того, как это можно настроить.

NUM_ANSWERS = 4
NUM_COMBOS = 2**NUM_ANSWERS
NO,YES = 'no','yes'

def index(answers):
    """ Convert a list of yes/no answers into binary number. """
    binstr = ''.join([('1' if a is 'yes' else '0') for a in answers])
    return int(binstr, 2)

def answers(index):
    """ Convert binary value of number into list of yes/no answers. """
    masks = [2**p for p in range(NUM_ANSWERS-1, -1, -1)]
    bits = [((index & m) / m) for m in masks]
    return [[NO,YES][b] for b in bits]

# condition expressions
cond_expr1 = lambda a1,a2,a3,a4: a1 is YES and a2 is NO  # a3,a4 ignored
cond_expr2 = lambda a1,a2,a3,a4: (
                ( a1 is YES and a2 is NO ) or ( a3 is YES and a4 is NO )
             )
# build tables for each condition
cond1 = []
cond2 = []
for i in range(NUM_COMBOS):
    ans_combo = answers(i)
    cond1.append( cond_expr1(*ans_combo) )
    cond2.append( cond_expr2(*ans_combo) )

# once tables are built, you can lookup the corresponding conditional
print cond1[ index(['yes', 'no', 'no', 'yes']) ]  # True
print cond2[ index(['yes', 'no', 'yes', 'no']) ]  # True
0 голосов
/ 31 октября 2010

итак, после некоторого чтения, основанного на подсказке Игнасио, я думаю, что оно у меня после некоторых модификаций строк.Однако все еще не совсем уверен, что это правильный подход.
Итак, моя переменная условия определена следующим образом:

cond = """if ( 'no' is 'yes' and 'no' is 'no' ):
   result.append[1]
else:
   result.append[0]
"""

Дополнительно я создаю переменную для сохранения результата условия, чтобы оценить его позже

result = []

Я запускаю exec на моей строке

exec(cond)

Наконец, я могу оценить результат.

if result[0] == 1
   print "Condition was met"
else: 
   print "Condition wasn't met"

Любые мысли или комментарии высоко ценятся.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...