将Python字符串转换为表达式

时间:2017-09-26 12:41:21

标签: python string sqlalchemy rethinkdb

某些软件包如SQLAlchemy和RethinkDB(我碰巧使用后者)需要将谓词表达式作为参数传递给函数。例如,RethinkDB的filter方法(https://rethinkdb.com/api/python/filter/)要求第一个参数是ReQL语法表达式,而不是字符串。

但是,我想基于我收到的REST API查询字符串以编程方式构建此表达式。例如,我可能会收到一个查询字符串,例如:

/?filter=name%3D%3DNick&filter=score%3D%3DA,score%3D%3DB

在这种情况下,我想将此查询字符串转换为谓词:

r.row['name'] == 'Nick' & (r.row['score'] == 'A' | r.row['score'] == 'B')

我可以使用我写的递归函数生成这个谓词作为字符串:

def process_filters(data):
    if isinstance(data, list):
        return ' & '.join([process_filters(val) for val in data])
    elif ',' in data:
        or_filters = data.split(',')
        return '(' + \
               ' | '.join(['(r.row["' + val.split('==', 1)[0] + '"] == ' + val.split('==', 1)[1] + ')' for val in or_filters]) + \
               ')'
    else:
        parts = data.split('==', 1)
        return '(r.row["' + parts[0] + '"] == ' + parts[1] + ')'

这个函数给了我一个字符串所需的谓词。但是,RethinkDB不会将此参数作为字符串处理。

r.filter(process_filters(query_string))

上面的命令将正常工作,因为r.filter需要一个表达式,例如:

r.filter(r.row['name'] == 'Nick')

不是:r.filter("r.row['name'] == 'Nick'")

如何将参数转换为表达式,同时仍然保持以编程方式从字符串构建谓词的灵活性,如我所拥有的那样?

编辑:eval实际 工作,但正如评论者指出的那样,这通常是不受欢迎的。我相信在这种特殊情况下它可能是最好的"解决方案,但我期待更多的想法...

1 个答案:

答案 0 :(得分:0)

x = "name=Nick"

key, value = x.split('=')
query = {r.row[key]: value}

r.filter(**query)

参考:What does ** (double star/asterisk) and * (star/asterisk) do for parameters?