如何将字符串作为逻辑参数进行评估?

时间:2017-11-02 23:30:33

标签: python loops robotframework

我正在使用Python for Robot Framework中的可嵌套For循环。我的目标是模仿100%的原始功能,所以如果满足某些条件,我需要能够打破For循环。我的解决方案是使用自定义关键字,在Python代码中评估的方式略有不同:exit_if

exit_if接受一个参数,一个字符串,并返回一个参数进行处理,一个布尔值。我想发送一个像'$var1 == $var2'这样的字符串(我已经解决了在机器人框架的For循环中创建的自定义变量名称周围需要括号的问题),让exit_if将字符串计算为它将是任何布尔表达式,如果表达式求值为True则返回True,如果表达式求值为False则返回False

一个简单的解决方案是让exit_if采用三个参数:var1operatorvar2。然后,在switch语句中,根据运算符计算变量。然而,这似乎不必要地笨拙和低效,所以我想找到一个更优雅的解决方案。

谷歌搜索后(可能我的谷歌搜索参数化不正确),我发现没有什么可以做我要求该程序做的事情,所以,鉴于这是一个编码问题,可以使未来的程序员受益,我转向这个网站。如何使用单个参数和no / minimum switch / if语句来实现三参数解决方案的效果?

编辑:我为原帖的简洁而道歉,在提出这个问题的过程中,我被赶出了办公室。

Robot Framework通过以类似框架的语言发送很长的信息单元列表来与我的For循环交互,然后我的代码处理这些单元格并转换为BuiltIn().run_keywords所需的格式。在Robot Framework中,这种格式看起来像这样(简单版本):

For Loop    IN RANGE    0    3   INDEX0
...     \\  Log to Console  INDEX0
...     \\  Run Keyword If  INDEX0 == 1  Log to Console  one

Robot Framework将其作为一行单元格处理,如下所示(单元格由|分隔:

For Loop|IN RANGE|0|2|INDEX0|\\|Log to Console|INDEX0|\\|Run Keyword If|INDEX0 == 1|Log to Console|one

我的代码将这些单元格转换为字符串列表。

['For Loop','IN RANGE','0','2','INDEX0','\\','Log to Console','INDEX0','\\','Run Keyword If','INDEX0 == 1','Log to Console','one']

然后,用于格式化它的代码使用BuiltIn().run_keywords()的每个循环迭代。因此,在迭代2(INDEX0 = 1):

kwords = ['Log to Console','1','AND','Run Keyword If','1 == 1','Log to Console','one']
BuiltIn().run_keywords(*kwords)

该系统太受限于Run Keywords的内置功能,我创建了一个我可以控制的镜像版本。它的功能与Run Keywords相同,但由self._run_keywords(*kwords)调用。

现在看来,该代码将无法运行。我正在尝试创建将处理1 == 1并将其传递给某个关键字的代码。鉴于我目前的目标是允许用户在循环中指定断点,我创建了一个名为exit_if的函数。 exit_if将(最终)以字符串的形式接收一个参数输入(如上所述,但不一定使用相同的语法),确定条件是否正确退出for循环,并退出for环。我希望它返回一个布尔值用于验证目的,因为我不完全确定exit_if如何与文件的其余部分进行交互。

我已经知道一种非常笨重的方法。获取输入(1 == 1),使用字符串解析来查找运算符和变量,使用switch语句来决定要进行的比较,进行比较,并(可能)将值返回到循环的其余部分,以便它可以阻止循环。

感谢Kindall,我现在可以通过字典和operator更轻松地完成此操作,但我希望能够提供更优雅的解决方案:

def exit_if(argument_string):
    if argument_string:
        return True
    else:
        return False

显然,为if语句提供现有字符串总是会产生True,但我希望能够将字符串转换为某些内容或将函数应用于它以将其转换为布尔值声明。如果这是不可能的,我需要采取笨重的方式,那很好。速度和美丽不是要求,但值得问。

2 个答案:

答案 0 :(得分:1)

使用operator模块和字典。

import operator

ops = {"==": operator.eq,
       "!=": operator.ne,
       "<":  operator.lt,
       "<=": operator.le,
       ">":  operator.gt,
       ">=": operator.ge}

def compare(a, op, b):
    return ops[op](a, b)

assert compare(3, "<", 4)

查看你的变量名并传入它们的值,我会留给你。

答案 1 :(得分:0)

您可以使用正则表达式来解决此问题。

import re

varSet = {'var1' : 1, 'var2' : 2 } #Dictionary for your variables

def exit_if(stringPassed):
    #(.*) - any character and its occurence
    pattern = re.compile(r'(.*) (.*) (.*)')
    #Looks for the matches, result.group(0) shows the result
    result  = pattern.match(stringPassed) 

    firstVariable  = varSet[result.group(1)] #'var1'
    operatorUsed   = result.group(2) #'=='
    secondVariable = varSet[result.group(3)] #'var2'

    if operatorUsed == '==':
        return firstVariable == secondVariable
    elif operatorUsed == '!=':
        return firstVariable != secondVariable
    elif operatorUsed == '<':
        return firstVariable < secondVariable
    elif operatorUsed == '<=':
        return firstVariable <= secondVariable
    elif operatorUsed == '>':
        return firstVariable > secondVariable
    elif operatorUSed == '>=':
        return firstVariable >= secondVariable
    else:
        print ('Some kind of error')

#Given that the pattern is always '$var1 == $var2'
print exit_if('var1 == var2') #prints False
print exit_if('var1 < var2') #prints True

有关re模块的更多信息:

https://docs.python.org/2/library/re.html

https://docs.python.org/3/library/re.html