首页 文章

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

提问于
浏览
177
>>> 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

12 回答

  • 0

    而不是使用.get,使用这样的列表应该没问题 . 只是用法差异 .

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

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

    >>> 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异常解决方案 . 我尝试了一个dummied down版本的 safe_list_get 解决方案,并使它更简单(没有默认值):

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

    没有基准来看看什么是最快的 .

  • -1

    如果需要圆形性质,单线风扇可以使用 %

    value = l[index] if abs(index)<len(l) else l[index%len(l)]
    
  • 73

    如果你想要第一个元素,这是有效的,如 my_list.get(0)

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

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

  • 36

    确保您没有收到错误的最佳方法是:

    for i in list:
        do_stuff(i)
    

    如果list为空,那么do_stuff将不会被执行 .

  • 3

    您的用例基本上仅与执行固定长度的数组和矩阵时相关,因此您可以知道它们之前有多长 . 在这种情况下,您通常也会在使用None或0填充它们之前创建它们,这样实际上您将使用的任何索引都已存在 .

    你可以这样说:我经常需要在字典上使用.get() . 作为一名全职程序员,经过十年的努力,我认为我从未在名单上找到它 . :)

  • 3

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

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

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

    您甚至可以将它monkeypatch到 __main__ 中的 __builtins__.list 构造函数,但由于大多数代码都不使用它,因此这种情况不太普遍 . 如果你只是想用你自己的代码创建的列表,你可以简单地继承 list 并添加 get 方法 .

  • 43

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

    class safelist(list):
        def get(self, index, default=None):
            try:
                return self.__getitem__(index)
            except IndexError:
                return default
    
    def _test():
        l = safelist(range(10))
        print l.get(20, "oops")
    
    if __name__ == "__main__":
        _test()
    
  • 13

    您可以做的最好的事情是将列表转换为dict,然后使用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')
    
  • 10

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

  • 30

    jose.angel.jimenez的积分


    对于“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']
    

    默认回退...

    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
    

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

  • 0

    试试这个:

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

相关问题