简体   繁体   English

小于或大于比较作为 Python 中的变量

[英]Less than Or Greater Than Comparison as a Variable in Python

I have a block of code in a function that does some comparisons, namely:我在一个函数中有一段代码可以进行一些比较,即:

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

Now sometimes I need to do those comparisons to be greater than, and sometimes I need them to be less than.现在有时我需要进行这些比较以大于,有时我需要它们小于。 All of the rest of the code is exactly the same.其余所有代码完全相同。 Now, I could just make two functions that reuse basically the same code, but before I do, is there some clean way to variabalize the comparison operator, so I could just use the same block of code and pass in the comparison as a variable?现在,我可以只创建两个重用基本相同代码的函数,但在此之前,是否有一些干净的方法可以对比较运算符进行变量化,所以我可以使用相同的代码块并将比较作为变量传递? Something like: compare(var1, var2, polarity) .类似于: compare(var1, var2, polarity) I know I can make this myself, but I'm wondering what the standard is in cases like this.我知道我可以自己做这个,但我想知道在这种情况下标准是什么。 Is there some pretty pythonic way of doing this I'm unaware of?有没有一些我不知道的非常pythonic的方式来做到这一点?

[Edit] Adding emphasis to the most important part of the question [/Edit] [编辑] 强调问题最重要的部分 [/编辑]

You can use the operator module ;您可以使用operator模块 it has functions that act as the comparison operators:它具有充当比较运算符的功能:

import operator

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

if comp(spam, eggs):

This'll use either test if spam is less then, or greater then eggs , depending on the truth of foobar .这将使用测试是否spam小于或大于eggs ,这取决于foobar的真实性。

This fits your comparison as a variable requirement exactly.这完全符合您作为可变要求的比较

This is certainly what I'd use to avoid repeating myself;这当然是我用来避免重复自己的方法; if you have two pieces of code that differ only in the comparison direction, use a function from operators to parameterize the comparison.如果您有两段代码在比较方向上有所不同,请使用operators中的函数来参数化比较。

I had the same question when trying to build a module for unknown ML models.在尝试为未知 ML 模型构建模块时,我遇到了同样的问题。 Some require a minimum score to perform, others a maximum score, depending on the metric used.有些需要最低分数才能执行,有些则需要最高分数,具体取决于所使用的指标。 I passed in a 'greater than' boolean variable and wrote a small function:我传入了一个“大于”布尔变量并编写了一个小函数:

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

I would not refactor this by making the operators dynamic in any way.我不会通过以任何方式使操作符动态化来重构它。 I think the comparisons aren't that similar and forcing them to look more similar obfuscates the code.我认为这些比较不是那么相似,并且迫使它们看起来更相似会混淆代码。 It's a bit of a red herring.这有点像红鲱鱼。

I would put the complex checks in a function, something like我会把复杂的检查放在一个函数中,比如

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

And then the code becomes:然后代码变成:

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

I guessed some names for the functions, and had to negate the logic in two of them to make the names work.我猜到了函数的一些名称,并且不得不否定其中两个中的逻辑以使名称起作用。

For some simple cases inverting the inputs sign can be the best approach.对于一些简单的情况,反转输入符号可能是最好的方法。 It does not require any develop process, just calling the function with opposite sign inputs:它不需要任何开发过程,只需调用带有相反符号输入的函数:

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

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

This approach is equivalent to permute >, <, >=, <= and max, min which is also usually useful because if you are inverting the signs "greater than" and "less that" you may also want to invert the maximum and the minimum for consistency.这种方法等效于置换>, <, >=, <=max, min ,这通常也很有用,因为如果您要反转符号“大于”和“小于”,您可能还想反转最大值和最低限度的一致性。

The big caveat of this approach is that complex functions can lead to incorrect results, if for instance the functions has middle step involving a mathematical operation such as exponentiation.这种方法的最大警告是复杂的函数可能导致不正确的结果,例如,如果函数具有涉及数学运算(如取幂)的中间步骤。

Other approach that doesn't suffer from the problem described is using a flag in the comparisons you want to invert, and maybe redefine the max/min function according to it too:其他不受所描述问题影响的方法是在要反转的比较中使用标志,并且也可以根据它重新定义 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM