Python的list.index()函数,当未找到时不会抛出异常

26 浏览
0 Comments

Python的list.index()函数,当未找到时不会抛出异常

如果列表中不存在该项,Python的list.index(x)会抛出一个异常。有没有更好的方法可以避免处理异常?

0
0 Comments

问题的出现原因:

Python中的列表(list)数据类型提供了index()函数,用于查找列表中某个元素的索引位置。然而,当要查找的元素不存在于列表中时,index()函数会抛出ValueError异常。有些情况下,我们希望在查找不到元素时返回一个默认值或者执行其他操作,而不是抛出异常。因此,有人提出了一个问题,希望能够实现一个不抛出异常的index()函数。

解决方法:

为了解决这个问题,可以通过自定义一个继承自list的类,并在该类中实现一个不抛出异常的index()函数。下面是一个示例代码:

class mylist(list):
  def index_withoutexception(self, i):
    try:
        return self.index(i)
    except:
        return -1

在上述代码中,我们创建了一个名为mylist的类,该类继承自list。然后,在该类中定义了一个名为index_withoutexception()的函数,该函数接受一个参数i,并尝试使用父类list的index()函数来查找元素i在列表中的索引位置。如果找到了元素i,则返回其索引位置;如果没有找到,则返回-1。

使用这个自定义的mylist类时,可以像使用普通列表一样使用它,并调用index_withoutexception()函数来查找元素,如下所示:

l = mylist([1, 2, 3, 4, 5]) # 这是与普通列表唯一的区别
l.append(4) # l是一个列表
l.index_withoutexception(19) # 返回-1或者其他你想要的值

需要注意的是,使用自定义的mylist类时,type(l) == list的结果会是False,因为mylist是list的子类。

此外,需要说明的是,尽管使用上述自定义的index_withoutexception()函数可以避免抛出异常,但实际上在函数内部仍会抛出异常,这可能会导致一定的性能开销。因此,需要根据具体情况权衡使用该函数的效果和性能。

0
0 Comments

Python中的list.index()函数在找不到指定元素时会抛出异常。然而,有些情况下我们并不关心是否找到元素,只想知道元素的索引。那么问题来了,如何在不抛出异常的情况下获取元素的索引呢?

在原问题中,某些情况下可以使用列表的in操作符来判断元素是否存在,这是一种很好的方法。但是,如果我们确实需要知道元素的索引,那么其他解决方案都需要遍历列表两次,这会带来很大的性能损耗。

此外,即使有一个返回-1的list.find函数,你仍然需要测试i是否等于-1并采取相应的操作。因此,我不同意原问题中应避免使用异常的假设。我认为异常是我们的朋友,它们不可怕,也不低效,实际上你需要熟悉异常才能写出优秀的代码。

所以,我认为最好的解决方案是使用try-except方法:

try:

i = somelist.index(x)

except ValueError:

# 处理异常

"处理异常"意味着你需要做你需要做的事情:将i设置为一个特殊值,抛出自定义异常,执行不同的代码分支等等。

这是Python原则"宁愿请求原谅,也不要征求许可(EAFP)"的一个例子,与"先看后跳(LBYL)"的if-then-else风格相对应。

有时候,我们会对自己的洞察力感到好笑。我刚刚写了上面的评论,没有注意到我两年前已经写了答案。只有当我试图为自己的答案投票时,Stack Overflow才提醒了我。

有人说异常很耗性能,你能量化一下异常的性能,并将其与其他答案进行比较吗?尽管经常说过早优化是一个很大的问题,但如果效率问题非常严重,那么使用其他方法会更差,除非上下文是一个内部循环。

请记住,替代方案是遍历列表两次,这可能是任意昂贵的。并且正如在stackoverflow.com/a/2522013/507544中指出的那样,异常可能非常快,甚至比其他方法更快,尽管细节很重要。所以对于大型列表来说,异常方法更快。希望能有一些分析的例子,帮助在性能关键的情况下做出选择。

你可能会认为这是其他语言的情况。Python并不运行本地机器代码,因此将异常实现为硬件中断是没有必要的。在C API中,异常是一个返回NULL值和全局设置的(每个线程)异常对象:docs.python.org/3/c-api/exceptions.html可以说,动态类型虚拟机的整个概念本身就是性能损失,但鉴于这一点,Python异常没有理由比其他Python语句更慢或更快。

0
0 Comments

问题出现的原因是在Python中,当使用list.index()函数查找元素在列表中的索引时,如果元素不存在,会抛出ValueError异常。然而,在某些情况下,我们可能不想要异常的抛出,而是希望得到一个特定的返回值来表示元素不存在。

对于这个问题,有两种解决方法。第一种方法是使用in关键字来判断元素是否在列表中,如下所示:

found = x in somelist

这种方法简洁明了,如果元素存在,则found为True,否则为False。

第二种方法是使用LBYL(Look Before You Leap)风格的条件表达式,如下所示:

i = somelist.index(x) if x in somelist else None

这种方法先判断元素是否在列表中,如果存在则使用index()函数获取索引,否则将i赋值为None。需要注意的是,这里将默认值从-1改为了None,因为-1是一个有效的列表索引。

其中,某些情况下了一种更快速的解决方法,可以在一次遍历中完成查找操作,如下所示:

i = next((i for i, t in enumerate(somelist) if x == t), None)

这种方法使用了生成器表达式和enumerate()函数,可以在列表中找到与目标元素相等的元素,并返回其索引。如果找不到,则返回None。需要注意的是,这种方法对于内置类型的列表而言,由于查找操作是由Python而不是C代码执行的,所以速度可能会慢一些。

总结起来,当我们需要查找列表中元素的索引,并且不想要异常抛出时,可以使用in关键字或者LBYL风格的条件表达式来解决这个问题。对于更高效的解决方案,可以使用生成器表达式和enumerate()函数在一次遍历中完成查找操作。

0