为什么列表没有像字典那样安全的“获取”方法?

2025-03-26 09:10:00
admin
原创
11
摘要:问题描述:为什么列表没有像字典那样安全的“获取”方法?>>> d = {'a':'b'} >>> d['a'] 'b' >>> d['c'] KeyError: 'c' >>> d.get('c', 'fail') 'fail' >...

问题描述:

为什么列表没有像字典那样安全的“获取”方法?

>>> d = {'a':'b'}
>>> d['a']
'b'
>>> d['c']
KeyError: 'c'
>>> d.get('c', 'fail')
'fail'

>>> l = [1]
>>> l[10]
IndexError: list index out of range

解决方案 1:

最终,它可能没有安全的.get方法,因为 adict是一个关联集合(值与名称相关联),其中检查键是否存在(并返回其值)而不引发异常是低效的,而避免访问列表元素的异常是非常简单的(因为该len方法非常快)。该.get方法允许您查询与名称相关联的值,而不是直接访问字典中的第 37 个项目(这更像您对列表的要求)。

当然,你也可以自己轻松实现:

def safe_list_get (l, idx, default):
  try:
    return l[idx]
  except IndexError:
    return default

您甚至可以将其 monkeypatch 到__builtins__.list中的构造函数上__main__,但这将是一个不太普遍的更改,因为大多数代码都不使用它。如果您只想将其用于您自己的代码创建的列表,您可以简单地将其子类化list并添加get方法。

解决方案 2:

如果您想要第一个元素,则此方法有效,例如my_list.get(0)

>>> my_list = [1,2,3]
>>> next(iter(my_list), 'fail')
1
>>> my_list = []
>>> next(iter(my_list), 'fail')
'fail'

我知道这并不是你所要求的,但它可能会对其他人有所帮助。

解决方案 3:

可能是因为它对于列表语义来说没有多大意义。但是,您可以通过子类化轻松创建自己的列表。

class safelist(list):
    def get(self, index, default=None):
        try:
            return self[index]
        except IndexError:
            return default

def _test():
    l = safelist(range(10))
    print l.get(20, "oops")

if __name__ == "__main__":
    _test()

解决方案 4:

对于列表,像这样使用应该没问题,而不是使用 .get。只是用法不同。

>>> l = [1]
>>> l[10] if 10 < len(l) else 'fail'
'fail'

解决方案 5:

感谢jose.angel.jimenez、Gus Bus和Marek R


对于“oneliner”粉丝来说……


如果您想要列表的第一个元素,或者如果列表为空则想要默认值,请尝试:

liste = ['a', 'b', 'c']
value = (liste[0:1] or ('default',))[0]
print(value)

返回a

liste = []
value = (liste[0:1] or ('default',))[0]
print(value)

返回default


其他元素的示例...

liste = ['a', 'b', 'c']
print(liste[0:1])  # returns ['a']
print(liste[1:2])  # returns ['b']
print(liste[2:3])  # returns ['c']
print(liste[3:4])  # returns []

使用默认后备……

liste = ['a', 'b', 'c']
print((liste[0:1] or ('default',))[0])  # returns a
print((liste[1:2] or ('default',))[0])  # returns b
print((liste[2:3] or ('default',))[0])  # returns c
print((liste[3:4] or ('default',))[0])  # returns default

可能更短:

liste = ['a', 'b', 'c']
value, = liste[:1] or ('default',)
print(value)  # returns a

看起来你需要等号前的逗号、等号和后面的括号。


更一般的:

liste = ['a', None, 'c']
f = lambda l, x, d='default': l[x] if -len(l) <= x < len(l) else d
print(f(liste, 0))   # returns a
print(f(liste, 1))   # returns None
print(f(liste, 2))   # returns c
print(f(liste, 3))   # returns default
print(f(liste, -1))  # returns c

对于虚假管理更为普遍:

liste = ['a', None, 'c']
f = lambda l, x, d='default': l[x] if -len(l) <= x < len(l) and l[x] not in (None, "", 0, False, [], {}, (), set(), frozenset(), b'', bytearray(b'')) else d
print(f(liste, 0))   # returns a
print(f(liste, 1))   # returns default
print(f(liste, 2))   # returns c
print(f(liste, 3))   # returns default
print(f(liste, -1))  # returns c

经过测试Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)

解决方案 6:

一个合理的做法是将列表转换为字典,然后使用 get 方法访问它:

>>> my_list = ['a', 'b', 'c', 'd', 'e']
>>> my_dict = dict(enumerate(my_list))
>>> print my_dict
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}
>>> my_dict.get(2)
'c'
>>> my_dict.get(10, 'N/A')

解决方案 7:

尝试一下:

>>> i = 3
>>> a = [1, 2, 3, 4]
>>> next(iter(a[i:]), 'fail')
4
>>> next(iter(a[i + 1:]), 'fail')
'fail'

解决方案 8:

所以我对此做了更多研究,结果发现对此并没有什么具体的东西。当我发现 list.index(value) 时我很兴奋,它返回指定项目的索引,但没有任何东西可以获取特定索引处的值。所以如果你不想使用 safe_list_get 解决方案,我认为它非常好。以下是一些 1 行 if 语句,可以根据场景为你完成工作:

>>> x = [1, 2, 3]
>>> el = x[4] if len(x) > 4 else 'No'
>>> el
'No'

您还可以使用 None 代替“No”,这更有意义:

>>> x = [1, 2, 3]
>>> i = 2
>>> el_i = x[i] if len(x) == i+1 else None

此外,如果您只想获取列表中的第一个或最后一个项目,也可以这样做

end_el = x[-1] if x else None

您也可以将它们变成函数,但我仍然喜欢 IndexError 异常解决方案。我尝试了该解决方案的简化版本safe_list_get,并使其更简单一些(无默认值):

def list_get(l, i):
    try:
        return l[i]
    except IndexError:
        return None

尚未进行基准测试来了解哪个是最快的。

解决方案 9:

字典用于查找。询问条目是否存在是有意义的。列表通常是迭代的。询问 L[10] 是否存在并不常见,而是询问 L 的长度是否为 11。

解决方案 10:

这不是一个非常通用的解决方案,但我遇到过这种情况,我期望列表的长度为 3 到 5(带有保护if),并且我将值分解为命名变量。我找到了一种简单而简洁的方法,包括:

foo = (argv + [None, None])[3]
bar = (argv + [None, None])[4]

现在foobar是列表中的第 4 和第 5 个值,或者None没有那么多值。

解决方案 11:

对于较小的索引值,您可以实现

my_list.get(index, default)

作为

(my_list + [default] * (index + 1))[index]

如果你事先知道索引是什么,那么这可以简化,例如如果你知道它是 1,那么你可以这样做

(my_list + [default, default])[index]

因为列表是向前打包的,所以我们唯一需要担心的失败情况是超出列表末尾。这种方法用足够的默认值填充列表末尾,以保证索引被覆盖。

解决方案 12:

如果你

  1. 想要一句台词,

  2. 最好不要在不需要的快乐代码路径中使用 try / except,并且

  3. 希望默认值是可选的,

你可以使用这个:

list_get = lambda l, x, d=None: d if not l[x:x+1] else l[x]

用法如下:

>>> list_get(['foo'], 4) == None
True
>>> list_get(['hootenanny'], 4, 'ho down!')
'ho down!'
>>> list_get([''], 0)
''

解决方案 13:

感谢 Brandon 的评论:

def safe_get(lst: list, i: int):
    return (lst[i:] or [None])[0]

mylist = [0, 1, 2]
print(safe_get(mylist, i=3))  # None
print(safe_get(mylist, i=-1)) # 2

解决方案 14:

您的用例基本上只适用于处理固定长度的数组和矩阵,这样您就可以提前知道它们的长度。在这种情况下,您通常还会提前创建它们并用 None 或 0 填充它们,这样您使用的任何索引实际上都已经存在。

您可以这样说:我经常需要在字典上使用 .get()。作为一名全职程序员十年后,我认为我从未在列表中需要它。:)

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2079  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1459  
  建筑行业正处于数字化转型的关键时期,建筑产品生命周期管理(PLM)系统的实施对于提升项目效率、质量和协同性至关重要。特别是在 2025 年,基于建筑信息模型(BIM)的项目进度优化工具成为众多建筑企业关注的焦点。这些工具不仅能够整合项目全生命周期的数据,还能通过精准的分析和模拟,为项目进度管理提供强大支持。BIM 与建...
plm是什么软件   0  
  PLM系统开发的重要性与现状PLM(产品生命周期管理)系统在现代企业的产品研发、生产与管理过程中扮演着至关重要的角色。它贯穿产品从概念设计到退役的整个生命周期,整合了产品数据、流程以及人员等多方面的资源,极大地提高了企业的协同效率和创新能力。通过PLM系统,企业能够实现产品信息的集中管理与共享,不同部门之间可以实时获取...
国产plm软件   0  
  PLM(产品生命周期管理)系统在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和技术的飞速发展,企业对PLM系统的迭代周期优化需求日益迫切。2025年敏捷认证对项目管理提出了新的要求,其中燃尽图作为一种强大的可视化工具,在PLM系统迭代周期优化中有着广泛且重要的应用。深入探讨这些应用,对于提升企业的项...
plm系统主要干什么的   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用