从字符串应用比较运算符

Apply comparison operator from string

我有一个 class Foo,其中包含一个数学比较运算 op 作为字符串:“<”、“>”或“=”。另外 Foo 包含一个数字 val.

class Foo:
  def __init__(self, operation: str, value: int):
    self.op = operation
    self.val = value

在我的代码中,我从输入中读取了一个数字,并使用 Foo 的包含操作将其与 Foo 的 class 示例值进行比较:

f = Foo('<', 15)
to_check = int(input())

if f.op == '<':
  if to_check < f.val:
    # ...
elif f.op == '>':
  if to_check > f.val:
    # ...
elif f.op == '=':
  if to_check == f.val:
    #...  

有什么方法可以更简单或更优雅吗?

这将适用于 eval。但必须谨慎使用eval!通过首先使用 ast.literal_eval 进行解析,请参阅此 post 以获得更安全的方法。 test a boolean expression in a Python string

更安全的方法可能不再算作“更简单”或“更优雅”。

class Foo:
    def __init__(self, operation: str, value: int):
        self.op = operation
        self.val = value

f = Foo('<', 15)
to_check = int(input())

eval(f'{to_check} {f.op} {f.val}')

这更优雅并且工作得很好:

class Foo:

    def __init__(self, op: str, val: int):
        self.op = op
        self.val = val

    def check(self, other):
        if isinstance(other, (int, float)):
            if self.op == '<': return self.val > other
            if self.op == '>': return self.val < other
            if self.op == '=': return self.val == other
            if self.op == '!=': return self.val != other
            if self.op == '>=': return self.val <= other
            if self.op == '<=': return self.val >= other
        return NotImplemented

f.check(other) 检查包含的操作的条件并 returns 它,换句话说:

f = Foo('<', 15)
if f.check(14):
    print('ok')

条件是True因为14小于15

备选方案: 如果我在程序中使用 Foo class,我想我会使用 @S-c-r-a-t-c-h-y 的方法。但这里有一个使用比较运算符的函数形式的优雅方法。

class Foo:
    def __init__(self, operation: str, value: int):
        self.op = operation
        self.val = value

f = Foo('<', 15)
to_check = int(12)

import operator
op_dict = {
    '>': operator.gt,
    '<': operator.lt,
    '==':operator.eq
}

op_dict.get(f.op)(to_check, f.val)

Python 已内置执行此操作。我们可以覆盖它们


class Foo:
    def __init__(self, operation: str, value: int):
        self.op = operation
        self.value = value
    def __repr__(self):
        
        return f"{self.__class__.__name__}({self.value} {self.op} input_X )"

    def __lt__(self, input_value):
        return self.value < input_value

    def __le__(self, input_value):
        return self.value <= input_value
    
    def __eq__(self, input_value):
        return self.value == input_value
    
    def __gt__(self, input_value):
        return self.value > input_value
    
    def __ge__(self, input_value):
        return self.value >= input_value
    
    def check(self, input_value:int):
        
        operations = {'<': self.__lt__,
                     '<=': self.__le__,
                     '==': self.__eq__,
                     '>': self.__gt__,
                     '>=':self.__ge__}
        
        return operations.get(self.op)( input_value)

演示


f = Foo(">=", 15)
print(f)
# Foo(15 >= input_X )

f.check(14)
# True
f.check(16)
# False

f > 16 
# False

f > 14
# True

感谢您的回答,但我也考虑过存储操作,而不是字符串,而是 lambda。对于我的情况来说,这似乎不是一个糟糕的解决方案:

less = lambda x, y: x < y
equal = lambda x, y: x == y

f = Foo(less, 15)
to_check = 12

if f.op(to_check, f.val):
  #...