在列表/数组索引处获取值,如果在Python中超出范围,则获取"无"

Chr*_*row 38 python

是否有清晰的方法来获取列表索引的值,或者None索引是否在Python中的范围或范围?

显而易见的方法是:

if len(the_list) > i:
    return the_list[i]
else:
    return None
Run Code Online (Sandbox Code Playgroud)

但是,详细程度会降低代码的可读性.是否有可以替代使用的干净,简单的单线程?

the*_*olf 43

尝试:

try:
    return the_list[i]
except IndexError:
    return None
Run Code Online (Sandbox Code Playgroud)

或者,一个班轮:

l[i] if i < len(l) else None
Run Code Online (Sandbox Code Playgroud)

例:

>>> l=range(5)
>>> i=6
>>> print(l[i] if i < len(l) else None)
None
>>> i=2
>>> print(l[i] if i < len(l) else None)
2
Run Code Online (Sandbox Code Playgroud)

  • @DanielDiPaolo:在python中,鼓励使用异常,而不是不赞成. (12认同)
  • 这有一个令人遗憾的副作用,就是使用异常作为控制流,而他的原始功能已经没有了,而且这种情况并不那么冗长. (6认同)
  • @BrtH:关于LBYL(看你跳跃之前(如果陈述))人群和EAFP(更容易请求宽恕然后允许(尝试/排除))人群的两个思想学校......但是通常使用例外这种方式绝对不是不赞成的......但我认为这在很大程度上取决于个人偏好 (4认同)
  • 我怀疑异常流是否会像简单的 if-else 一样高效。 (3认同)
  • 除了在 Python 异常流中 _is_ 更高性能:异常在 Python 中_非常_ 轻,只有在发生异常时才会产生(有限的)开销。if 语句意味着在代码无论如何都会执行时运行比较。检查 [this answer](/sf/ask/176540381/) 和 [this doc](https://docs.python.org/2/faq/ design.html#how-fast-are-exceptions) (2认同)

Has*_*ken 17

我发现列表切片对此有好处:

>>> x = [1, 2, 3]
>>> a = x [1:2]
>>> a
[2]
>>> b = x [4:5]
>>> b
[]
Run Code Online (Sandbox Code Playgroud)

因此,如果你想要x [i],请始终访问x [i:i + 1].如果存在,您将获得包含所需元素的列表.否则,您将获得一个空列表.

  • 附录:这可以扩展为`my_list [idx:idx + 1]或"Default_value"`.可读且简洁!:) (3认同)

dsp*_*els 9

如果您正在处理小列表,则不需要添加 if 语句或类似内容。一个简单的解决方案是将列表转换为字典。然后你可以使用dict.get

table = dict(enumerate(the_list))
return table.get(i)
Run Code Online (Sandbox Code Playgroud)

您甚至可以None使用 的第二个参数设置另一个默认值而不是dict.get。例如,如果索引超出范围,则用于table.get(i, 'unknown')返回'unknown'

请注意,此方法不适用于负索引。


Aka*_*all 8

出于您的目的,如果不满足给定条件,您可以将该else部分排除为None默认返回.

def return_ele(x, i):
    if len(x) > i: return x[i]
Run Code Online (Sandbox Code Playgroud)

结果

>>> x = [2,3,4]
>>> b = return_ele(x, 2)
>>> b
4
>>> b = return_ele(x, 5)
>>> b
>>> type(b)
<type 'NoneType'>
Run Code Online (Sandbox Code Playgroud)


Emm*_*ler 7

return the_list[i] if len(the_list) > i else None
Run Code Online (Sandbox Code Playgroud)

  • @semicolon因为详细程度不仅仅基于行数...... (4认同)
  • @semicolon另一个糟糕的指标. (2认同)

And*_*cki 7

结合切片和迭代

next(iter(the_list[i:i+1]), None)
Run Code Online (Sandbox Code Playgroud)

  • @MichaelGeary:我不明白你为什么认为这是一个笑话。在撰写本文时,这是唯一的答案,它不会两次引用列表,当您的列表是临时对象时,这非常方便。除此之外,您还可以在一个语句中选择替代返回值。 (6认同)
  • 读者注意:我可以解释这个答案的唯一方式是它是一个笑话。你永远不应该用它来解决OP问题中的问题。 (2认同)

小智 7

1. 如果...否则...

l = [1, 2, 3, 4, 5]
for i, current in enumerate(l):
    following = l[i + 1] if i + 1 < len(l) else None
    print(current, following)
# 1 2
# 2 3
# 3 4
# 4 5
# 5 None
Run Code Online (Sandbox Code Playgroud)

2. 尝试...除了...

l = [1, 2, 3, 4, 5]
for i, current in enumerate(l):
    try:
        following = l[i + 1]
    except IndexError:
        following = None
    print(current, following)
# 1 2
# 2 3
# 3 4
# 4 5
# 5 None
Run Code Online (Sandbox Code Playgroud)

3. 字典

适合小清单

l = [1, 2, 3, 4, 5]
dl = dict(enumerate(l))
for i, current in enumerate(l):
    following = dl.get(i + 1)
    print(current, following)
# 1 2
# 2 3
# 3 4
# 4 5
# 5 None
Run Code Online (Sandbox Code Playgroud)

4. 列表切片

l = [1, 2, 3, 4, 5]
for i, current in enumerate(l):
    following = next(iter(l[i + 1:i + 2]), None)
    print(current, following)
# 1 2
# 2 3
# 3 4
# 4 5
# 5 None
Run Code Online (Sandbox Code Playgroud)

5. itertools.zip_longest

from itertools import zip_longest

l = [1, 2, 3, 4, 5]
for i, (current, following) in enumerate(zip_longest(l, l[1:])):
    print(current, following)
# 1 2
# 2 3
# 3 4
# 4 5
# 5 None
Run Code Online (Sandbox Code Playgroud)

使用 Jupyter magic 命令%%timeit

在里面

from itertools import zip_longest

l = list(range(10000000))
Run Code Online (Sandbox Code Playgroud)

结果

方法 消耗
如果别的... 2.62秒
尝试...除了... 1.14秒
词典 2.61秒
列表切片 3.75秒
itertools.zip_longest 1.14秒