在Python中将“小于”或“大于”比较作为变量

13 投票
4 回答
11271 浏览
提问于 2025-04-18 04:38

我有一段代码在一个函数里,主要是用来做一些比较的,具体代码如下:

if customer_info['total_dls'] < min_training_actions \
or customer_info['percentage'] > train_perc_cutoff:
    continue
elif customer_id not in test_set \
or test_set[customer_id]['total_dls'] < min_testing_actions:
    num_uncertain +=1
    continue
elif test_set[customer_id]['percentage'] <= test_perc_cutoff:
    num_correct +=1
else:
    num_incorrect +=1

有时候我需要进行“大于”的比较,有时候又需要“小于”的比较。其他的代码都是一样的。现在,我可以简单地写两个函数,基本上重复使用同样的代码,但在这之前,我想知道有没有什么简单的方法,可以把比较的方式变成一个变量,这样我就可以用同一段代码,只需传入比较方式作为参数?比如说:compare(var1, var2, polarity)我知道我可以自己实现这个,但我想知道在这种情况下有没有什么标准的做法。有没有什么比较“pythonic”的方法是我不知道的?

[编辑] 强调问题中最重要的部分 [/编辑]

4 个回答

1

在一些简单的情况下,反转输入的符号可能是最好的方法。这种方法不需要任何开发过程,只需用相反符号的输入调用函数即可:

a = 3
b = 5
def func(a,b):
    return a>b

func(a, b) -> False
func(-b, -a) -> True

这种方法相当于交换 >, <, >=, <= 以及 max, min,这通常也很有用,因为如果你反转了“更大于”和“更小于”,你可能也想为了保持一致性而反转最大值和最小值。

这种方法的大问题是,对于复杂的函数,如果函数中有涉及数学运算的中间步骤,比如指数运算,可能会导致错误的结果。

另一种不受上述问题影响的方法是,在你想要反转的比较中使用一个标志,可能还需要根据这个标志重新定义最大值和最小值的函数:

def func(a,b, rev=False):
    rev = -1 if rev else 1
    return rev*a>rev*b

func(a, b) -> False
func(a, b, True) -> True
1

我不会通过让操作符变得动态来重构这个代码。我觉得这些比较并不那么相似,强行让它们看起来更相似反而会让代码变得难以理解。这有点像是误导。

我会把复杂的检查放到一个函数里,像这样:

def customer_trained_enough(customer_info):
    return (
        customer_info['total_dls'] < min_training_actions
        or customer_info['percentage'] > train_perc_cutoff)

def customer_tested_enough(test_info):
    return test_info['total_dls'] >= min_testing_actions

def percentage_too_high(test_info):
    return test_info['percentage'] > test_perc_cutoff

然后代码就变成了:

if customer_trained_enough(customer_info):
    continue
if (customer_id not in test_set or
    not customer_tested_enough(test_set[customer_id])):
    num_uncertain += 1
elif not percentage_too_high(test_set[customer_id]):
    num_correct += 1
      else:
    num_incorrect += 1

我给这些函数猜了一些名字,还得把其中两个的逻辑反转一下,才能让名字合理。

2

我在尝试为一些不太了解的机器学习模型构建模块时,也遇到了同样的问题。有些模型需要一个最低分数才能正常工作,而有些则需要一个最高分数,这取决于使用的评估标准。我传入了一个“是否大于”的布尔变量,并写了一个小函数:

def is_better(gt,a,b): 
    return a>b if gt else a<b
22

你可以使用operator模块,里面有一些函数可以当作比较运算符来用:

import operator

if foobar:
    comp = operator.lt
else:
    comp = operator.gt

if comp(spam, eggs):

这段代码会根据foobar的真假来判断spam是小于还是大于eggs

这正好符合你对将比较作为变量的需求。

我会用这个方法来避免重复代码;如果你有两段代码,只有比较的方向不同,那就可以用operators里的函数来参数化这个比较。

撰写回答