如果该项不存在,Python的list.index(x)会引发异常。 有没有一种不需要处理异常的更好的方法呢?
要看。 你在乎吗?
不必要
最好的方法取决于在什么都没发现的情况下该做什么。 即使我们的list.find返回了-1,您仍然需要测试以查看i == -1并采取一些措施。
Raymond-似乎应该由我决定我的代码是否可以处理None索引,而不是强制执行异常。 但是后来,我仍然在学习如何成为Pythonic ...
为什么列表可能没有像字典那样的安全"获取"方法的副本?
正如我在回答中澄清的,@ yarin如果不需要索引,则需要in关键字。 但是,如果您这样做,我认为雷蒙德(Raymond)有一个好处,而例外是解决此问题的最佳方法。
如果您不在乎匹配元素在哪里,请使用:
1found = x in somelist
如果您确实需要,请使用带有条件表达式的LBYL样式:
1i = somelist.index(x) if x in somelist else None
感谢Raymond,这是最简洁的答案(再次,将默认值从-1更改为None,因为-1是有效的列表索引)
感谢Raymond,LBYL对我来说是新参考。
但是,这种方法是否比仅运行index()慢得多?毕竟,您必须看两次:一次是为了存在,一次是为了索引。这就是为什么C ++容器没有exists(),只有find()的原因。
正如@frans所说,这需要两次查找,但这是另一种可以一次完成工作的方法:i = next((i for i, t in enumerate(somelist) if x == t), None)
实现自己的列表索引?
6class mylist(list):
def index_withoutexception(self,i):
try:
return self.index(i)
except:
return -1
因此,您可以使用list,并与index2一起使用,以防出现错误时返回所需的内容。
您可以像这样使用它:
3l = mylist([1,2,3,4,5]) # This is the only difference with a real list
l.append(4) # l is a list.
l.index_withoutexception(19) # return -1 or what you want
请注意,这可能会破坏一些代码:此处的type(l) == list是False。
另外-我不是很积极,但是在我看来,如果目标是避免引发异常(如果经常发生则代价很高),那么这将无法实现。它将返回-1,但是在内部仍然会引发异常,这仍然是昂贵的。
编写一个满足您需要的函数:
5def find_in_iterable(x, iterable):
for i, item in enumerate(iterable):
if item == x:
return i
return None
如果您只需要知道项目是否存在,而不需要索引,则可以使用in:
1x in yourlist
谢谢-但是我希望预先包装一些东西
PS -1是有效的列表索引-您需要返回无
@Yarin:之所以选择-1是为了与现有的Python习惯用法保持一致,例如abc.find(x) == -1,但是None也会起作用。病态更新我的答案。
是的,.find()做到这一点很奇怪-似乎与Python的负索引不一致。
TL; DR:例外是您的朋友,并且是所述问题的最佳解决方案。
OP在评论中澄清说,对于他们的用例,知道索引是什么实际上并不重要。如公认的答案所述,如果您不在乎,使用x in somelist是最佳答案。
但是,正如原始问题所暗示的那样,我将假设您确实在乎索引是什么。在这种情况下,我会注意到,所有其他解决方案都需要对列表进行两次扫描,这会带来较大的性能损失。
此外,正如尊敬的雷蒙德·海廷格(Raymond Hettinger)在评论中写道
Even if we had list.find that returned a -1 you would still need to test to see if the i == -1 and take some action.
因此,我将推回原始问题中应该避免例外的假设。我建议例外是你的朋友。没什么可担心的,它们并不是低效的,实际上,您需要精通它们才能编写好的代码。
所以我认为最好的答案是简单地使用try-except方法:
try:
i = somelist.index(x)
except ValueError:
# deal with it
"处理"只是意味着要做您需要做的事情:将i设置为哨兵值,引发您自己的异常,遵循其他代码分支等。
就在这里。您可以例如。做类似的事情:
1test = lambda l, e: l.index(e) if e in l else None
像这样工作:
7>>> a = ['a', 'b', 'c', 'g', 'c']
>>> test(a, 'b')
1
>>> test(a, 'c')
2
>>> test(a, 't')
None
因此,基本上,test()将返回给定列表(第一个参数)中元素(第二个参数)的索引,除非尚未找到(在这种情况下,它将返回None,但可以是您认为合适的任何值) )。
希望这可以帮助
3lst= ','.join('qwerty').split(',') # create list
i='a' #srch string
lst.index(i) if i in lst else None
如果您不在乎序列中的位置,只需关心它的存在,然后使用in运算符。否则,编写一个重构异常处理的函数。
5def inlist(needle, haystack):
try:
return haystack.index(needle)
except ...:
return -1
我已经发布了一个答案,该答案使用in检查存在性并最终返回索引,但是我看到您知道该方法,并决定使用可能引发的处理异常。我的问题是:为什么您选择捕获异常而不是首先检查haystack是否存在needle?有什么理由吗?
@Tadeck:由于Python规则不完整,"请求宽恕比允许许可容易"。
谢谢:)我刚刚在Python词汇表中找到了它,其中EAFP(比请求许可更容易获得宽恕)被显示为与LBYL相反的东西。的确,EAFP已经被命名为通用的Python编码风格,所以它并不是那么不成文:)再次感谢!
您实际上并不需要except ...:行中的...。
我喜欢使用Web2py的List类,该类位于其gluon软件包的存储模块中。存储模块提供类似列表(List)和类似字典(Storage)的数据结构,当找不到元素时,它们不会引发错误。
首先下载web2py的源代码,然后将gluon软件包文件夹复制粘贴到python安装的site-packages中。
现在尝试一下:
6>>> from gluon.storage import List
>>> L = List(['a','b','c'])
>>> print L(2)
c
>>> print L(3) #No IndexError!
None
注意,它也可以像常规列表一样运行:
6>>> print L[3]
Traceback (most recent call last):
File"", line 1, in
l[3]
IndexError: list index out of range
好主意,谢谢。)def __call__(self, idx, df=None): return self[idx] if 0<=idx
没有内置的方法可以做您想做的事。
这是一篇很好的文章,可能对您有所帮助:为什么列表没有像字典一样安全的"获取"方法?
该文章是关于数组索引的,带有IndexError: list index out of range问题,而不是此处描述的带有ValueError: is not in list问题的index()方法。