【问题标题】:reversed condition with different outcome不同结果的逆转条件
【发布时间】:2020-10-26 12:21:39
【问题描述】:

'''

import operator
def sorted (a, xs):
   '''a is the operator, xs is a list''' 
  if a == operator.gt:
       for i in range(len(xs)):
           if xs[i] < xs[i+1]:
               return False
           else: True

'''

如果我把它写在相反的条件下,就会出现错误“IndexError: list index out of range”

 if a == operator.gt:
   for i in range(len(xs)):
       if xs[i] > xs[i+1]:
           return True
       else: False

【问题讨论】:

  • 请提供使用的变量示例。尽管我的猜测是,在第一种情况下,您会在列表末尾之前遇到条件,而在第二种情况下则不会。
  • 排序(operator.gt, [2, 2, 4, 5, 8, 9]),它适用于第一个代码

标签: python list operator-keyword


【解决方案1】:

主要问题是您写了for i in range(len(xs)):,然后尝试访问xs[i+1]。这势必会在循环的最后一次迭代中引发异常IndexError: list index out of range

您的代码的第二个问题是else: Trueelse: False 部分,它们什么都不做。您可能忘记了关键字return。就目前而言,您的代码相当于:

import operator
def sorted (a, xs):
   '''a is the operator, xs is a list''' 
  if a == operator.gt:
       for i in range(len(xs)):
           if xs[i] < xs[i+1]:
               return False

i == len(xs)-1i+1 为1 太大时,将在循环的最后一次迭代中引发异常。

你是否会得到异常IndexError: list index out of range取决于for循环是否有机会进行它的最后一次迭代,或者函数是否会在return的最后一次迭代之前for -循环。

另一个问题是你调用了你的函数sorted,它已经是python中内置函数的名称。重复使用该名称将导致混淆和可能的错误。由于您的函数不返回排序列表,而是测试列表是否排序,因此我建议将其称为 is_sorted

同时解决这两个问题:

  • 删除else 分支;
  • 添加return True 在与for关键字相同的缩进级别;
  • range(len(xs)) 替换为range(len(xs)-1)

您了解此处需要-1 吗?想象一下,如果您的列表有 3 个元素。你需要多少次比较才能检查它是否排序?您需要将第一个元素与第二个元素进行比较;然后是第二个和第三个;就是这样。 3 个元素只有 2 次比较。如果省略-1,您将尝试将第三个元素与虚构的第四个元素进行比较,python 解释器会抱怨并引发IndexError: list index out of range

最终代码:

import operator
def is_sorted (a, xs):
   '''a is the operator, xs is a list''' 
  if a == operator.gt:
       for i in range(len(xs)-1):
           if xs[i] < xs[i+1]:
               return False
       return True

遵循python约定:可选参数reverse

比较参数aoperator.gt 有点笨拙,因为您编写的函数无论如何都不适用于自定义运算符。我建议遵循python builtins sorted and list.sort() 的约定,它使用可选参数reverse 默认为False

代码:

def is_sorted(xs, reverse=False):
  if not reverse:
    for i in range(len(xs)-1):
      if xs[i] > xs[i+1]:
        return False
    return True
  else:
    for i in range(len(xs)-1):
      if xs[i] < xs[i+1]:
        return False
    return True

进一步的改进建议:

  • 添加可选参数key,如python内置sortedlist.sort
  • 让用户给你一个比较运算符,并直接使用该运算符而不是&lt;&gt;

使用any or all的替代代码

def is_sorted(xs):
  return all(xs[i] <= xs[i+1] for i in range(len(xs)-1))

def is_sorted(xs):
  return not any(xs[i] > xs[i+1] for i in range(len(xs)-1))

【讨论】:

  • 然而 is_sorted (operator.gt, [2, 2, 4, 5, 8, 9]) 返回 True 是不对的
  • @SummerPan 我刚刚测试过它,它返回 False。你说的是哪个版本?
  • 现在可以了,非常感谢,我现在只关注第一个版本。
  • @SummerPan 请注意,如果aoperator.lt 等运算符,那么您可以写成a(x,y) 而不是x &lt; y。我强烈建议你不要写if a == operator.gt
猜你喜欢
  • 2021-02-23
  • 1970-01-01
  • 1970-01-01
  • 2019-01-04
  • 2021-10-12
  • 2018-11-01
  • 2015-09-26
  • 1970-01-01
  • 2021-03-20
相关资源
最近更新 更多