基于字符串值执行<,>,==,<=或>=操作的pythonic方法?



假设我有一个字符串op可以等于<,>,==,<=或>=。

我想对两个值执行关联的操作。有没有比下面显示的简单 if/else 方法更 pythonic 的方法可以做到这一点?

def doit(op, val1, val2):
if op == ">":
return val1 > val2
elif op == "<":
return val1 < val2
etc....

您可以使用operator

import operator
operations = {'>':'gt', '>=':'ge', '<':'lt', '==':'eq', '!=':'ne', '<=':'le'}
def doit(op, *vals):
return getattr(operator, operations[op])(*vals)

使用getattr相当于调用operator.eqoperator.lt等,只是要调用的函数的字符串名传递给getattr

编辑:更短的解决方案需要从operator导入特定功能:

from operator import gt, ge, lt, eq, ne, le
operations = {'>':gt, '>=':ge, '<':lt, '==':eq, '!=':ne, '<=':le}
def doit(op, *vals):
return operations[op](*vals)

Ajax1234 答案中的第二个版本可能是您真正想要的,但是,为了好玩,您甚至可以动态地将运算符从operator函数中提取出来:

import inspect
import operator
import re
ops = inspect.getmembers(operator, callable)
pubops = (op for opname, op in ops if not opname.startswith('_'))
opmatches = ((op, re.search('ame as as*(.*?)s*b.', op.__doc__)) for op in pubops)
operations = {match.group(1): op for op, match in opmatches if match}

现在operations不仅有比较运算符,而且每个可以覆盖运算符。

我不确定这有什么用。1(我确实说过你可能想要阿贾克斯的答案。但是一起打耳光很有趣。


1. 我能想到的最好的:再写几行代码(使用ast),你可以写一个opexpr_eval,只允许用括号括起来的运算符表达式literal_eval-able 值,而不允许其他任何内容,这不会比literal_eval本身更危险。(即便如此,我也不确定iops对你有什么好处。或者 matmul,因为 numpy 数组不是文字价值可评估的。但是你可以玩得开心,测试是否(1, (2, 3)) is (1, (2, 3)).:)

最新更新