gpt4 book ai didi

python - 实现与 `dict.get` 提供的默认功能等效的列表

转载 作者:行者123 更新时间:2023-11-28 22:25:20 28 4
gpt4 key购买 nike

dict 有一个方便的 get 版本:

get(key[, default])

Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.

大胆强调我的,因为我看了看,找不到列表的等效版本。所以我实现了自己的:

In [148]: class myList(list):
...: def pop(self, idx=-1, default=None):
...: try:
...: return super().pop(idx)
...: except IndexError:
...: return default

这按预期工作:

In [149]: l = myList([1, 2, 3, 4, 5])

In [150]: l.pop()
Out[150]: 5

In [151]: l.pop(12345, 'default')
Out[151]: 'default'

因为这个有效,这也可以扩展到集合。不管怎样,我有几个问题:

  1. 是否有一个更简单/内置/第 3 方等同于我所做的,不需要我扩展 list 类?

  2. 如果没有,是否有任何特殊原因?我相信这将是一种有用的行为。

我能想到的一些特定用例是在您不知道其大小的列表上调用 pop,在您不想去的地方调用,或者无法捕获错误,例如列表组件。


This question探讨了相同的主题,但答案不符合我的要求,正如我在上面所解释的那样。

最佳答案

它只为字典实现的一个原因是检查 if key in some_dict 在最坏的情况下并不总是一个 O(1) 操作O(n)。但即使查找是 O(1),它实际上也是一个昂贵的操作,因为您需要对 key 进行哈希处理,然后如果有匹配项,您需要比较 key 与存储的 key 是​​否相等。这使得 LBYL字典非常昂贵。

另一方面,对于列表,检查索引是否在边界内是一项成本非常低的操作。我的意思是你可以用一个简单的方法检查它是否在范围内:

valid_index = -len(some_list) <= index < len(some_list)

但这仅适用于 LBYL 方法。人们总是可以使用 EAFP并捕获异常。

这应该对列表和字典施加相同的开销。那么为什么 dict 有一个 get 方法来避免异常处理呢?原因实际上很简单:dict 是几乎所有内容的基本构建 block 。大多数类和所有模块本质上只是字典,很多用户代码实际上使用字典。拥有一种可以在没有异常处理开销的情况下保证返回的方法过去是(现在仍然是)值得的。

对于列表它也可能有用(我在这一点上不太确定)但我认为在大多数情况下当它抛出 IndexError 时它是偶然发生的,而不是故意的。因此,如果它返回 None,它会隐藏一个真正的“错误”。

这只是我对此的推理。我可能是 Python 开发人员对当前行为有完全不同的原因。


关于您的第一个问题:

Is there an easier/inbuilt/3rd party equivalent to what I've done that doesn't require me to extend the list class?

此外,我不知道用于这些操作的标准库或第 3 方模块以及列表或集合的默认值。一些库实现了一个“稀疏列表”(一个填充有默认值的列表),但我看过的那些库不处理“空列表”的情况,它们使用一个默认值作为完整列表.

但是,如果您不想自己进行“异常处理”,可能会有一些有趣的选项:

  • 来自 itertools documentation pageiter_except 配方当指定的异常发生时停止调用函数:

    def iter_except(func, exception, first=None):
    # Copied verbatim from the above mentioned documentation page
    try:
    if first is not None:
    yield first()
    while True:
    yield func()
    except exception:
    pass

    >>> l = [1,2,3,4]
    >>> list(iter_except(l.pop, IndexError))
    [4, 3, 2, 1]
  • contextlib.suppress

    import contextlib
    def pop_with_default(lst, ind=-1, default=None):
    with contextlib.suppress(IndexError):
    return lst.pop(ind)
    return default

    >>> pop_with_default([1,2,3], 5, 'abc')
    'abc'

这里处理一般问题的另一种方法是创建一个调用另一个函数的函数,在指定异常的情况下将返回默认值,否则返回函数调用的结果:

def call_with_default(func, default=None, *exceptions):
def inner(*args, **kwargs):
try:
res = func(*args, **kwargs)
except exceptions:
res = default
return res
return inner

>>> a = [1,2,3,4]
>>> a_pop_with_default = call_with_default(a.pop, 'abc', IndexError)
>>> [a_pop_with_default(2) for _ in range(10)]
[3, 4, 'abc', 'abc', 'abc', 'abc', 'abc', 'abc', 'abc', 'abc']

关于python - 实现与 `dict.get` 提供的默认功能等效的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45561802/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com