实现三个相似整数范围运算符的 Pythonic 方式?

标签 python operators

我正在研究一个循环问题。在这个问题中,我们将对象放在大小为 MAX 的环上,并分配了从(0 到 MAX-1)的 ID。

我有三个简单的函数来测试范围包含。 inRange(i,j,k) 测试 i 是否在循环区间 [j,k[(助记符是 i inRange(j,k))。我对范围 ]j,k[ 和 ]j,k] 也有同样的看法。

这三种方法中的代码看起来从一种方法到另一种方法是重复的:

def inRange(i,j,k):
    """
    Returns True if i in [j, k[
    * 0 <= i, j, k < MAX
    * no order is assumed between j and k: we can have k < j
    """
    if j <= k:
        return j <= i < k
    # j > k :
    return j <= i or i < k

def inStrictRange(i,j,k):
    """
    Returns True if i in ]j, k[
    * 0 <= i, j, k < MAX
    * no order is assumed between j and k: we can have k < j
    """
    if j <= k:
        return j < i < k
    # j > k :
    return j < i or i < k

def inRange2(i,j,k):
    """
    Returns True if i in ]j, k]
    * 0 <= i, j, k < MAX
    * no order is assumed between j and k: we can have k < j
    """
    if j <= k:
        return j < i <= k
    # j > k :
    return j < i or i <= k

您知道实现这三种方法的更简洁的方法吗?毕竟,只有运营商在改变?!

经过思考更好的解决方案,我想出了:

from operator import lt, le
def _compare(i,j,k, op1, op2):
    if j <= k:
        return op1(j,i) and op2(i,k)
    return op1(j,i) or op2(i,k)

def inRange(i,j,k):
    return _compare(i,j,k, le, lt)
def inStrictRange(i,j,k):
    return _compare(i,j,k, lt, lt)
def inRange2(i,j,k):
    return _compare(i,j,k, lt, le)

好点了吗?你能想出更直观的东西吗? 简而言之,编写这三个运算符的 Pythonic 方式是什么?

此外,我讨厌 inRange、inStrictRange、inRange2 名称,但我想不出清晰的名称。有什么想法吗?

谢谢。

最佳答案

两个 Zen of Python原则跃入脑海:

  • 简单胜于复杂。
  • 应该有一种——最好只有一种——显而易见的方法来做到这一点。

范围

Python 内置函数range(start, end) 生成一个从startend 的列表。1 该列表的第一个元素是 start,最后一个元素是 end - 1

没有range_strict 函数或inclusive_range 函数。当我开始使用 Python 时,这对我来说非常尴尬。 (“我只想要一个从 ab 的列表!这有多难,Guido?”)但是,调用 range 时使用的约定code> 函数简单易记,由于没有多个函数,所以很容易记住每次如何生成一个范围。

推荐

您可能已经猜到了,我的建议是只创建一个函数来测试 i 是否在 [j, k 范围内>).事实上,我的建议是只保留现有的 inRange 函数。

(由于您的问题特别提到了 Pythonicity,我建议您将该函数命名为 in_range 以更好地适应 Python Style Guide。)

理由

为什么这是个好主意?

  • 单一功能简单易懂。学习如何使用它非常容易。

    当然,您的三个起始函数中的每一个都可以这样说。到目前为止一切顺利。

  • 只有一个函数需要学习。没有三个函数的名称必须相似。

    鉴于您的三个函数的名称和行为相似,您在某种程度上可能会使用错误的函数。除了边缘情况外,函数返回相同的值这一事实使情况更加复杂,这可能会导致难以发现的差一错误。通过只提供一个功能,您知道自己不会犯这样的错误。

  • 函数易于编辑。

    您不太可能需要调试或编辑如此简单的一段代码。然而,如果您需要这样做,您只需编辑这一项功能。使用您原来的三个功能,您必须在三个地方进行相同的编辑。在您的 self 回答中修改后的代码,由于运算符的混淆,代码的直观性略有下降。

  • 范围的“大小”显而易见。

    对于您将使用 inRange(i, j, k) 的给定环,很明显范围 [j 将覆盖多少元素,< em>k).这是代码。

    if j <= k:
        size = k - j
    if j > k:
        size = k - j + MAX
    

    因此

    size = (k - j) % MAX
    

注意事项

我是从一个完全通用的角度来解决这个问题的,例如为公开发布的库编写函数的人的角度。由于我不知道你的问题领域,我不能说这是否是一个实用的解决方案。

使用此解决方案可能意味着对调用这些函数的代码进行相当多的重构。查看此代码,看看编辑它是否非常困难或乏味。


1:其实就是range([start], end, [step])。不过,我相信您明白我的意思。

关于实现三个相似整数范围运算符的 Pythonic 方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/985309/

相关文章:

ios - 如何在 swift3 中增加 String.Index?

python - keras model.fit 函数打印的准确率与验证集还是训练集有关?

python - 在几天内获得 Pandas DatetimeIndex 系列差异的最佳方法?

python - Flask 在 try catch 运行时错误后无法引发 HTTP 异常

operators - 为什么 Io REPL 和解释器给我两个不同的值?

c++ - C++ 中派生类的等式测试

python - 如何制作在 matplotlib 中循环的箭头?

python - 如何将数组项本身转换为数组Python

c - i = (i,++i, 1) + 1; 是什么意思?做?

c++ - 如何正确重载 + 运算符