空列表的安全max()函数

时间:2016-03-22 15:04:44

标签: python list exception error-handling max

评估,

max_val = max(a)

会导致错误,

ValueError: max() arg is an empty sequence

除了tryexcept捕获之外,还有更好的方法来防范此错误吗?

a = []
try:
    max_val = max(a)
except ValueError:
    max_val = default 

7 个答案:

答案 0 :(得分:43)

在Python 3.4+中,您可以使用default keyword argument

>>> max([], default=99)
99

在较低版本中,您可以使用or

>>> max([] or [99])
99

注意:第二种方法不适用于所有迭代。特别是对于迭代器来说,除了被认为是真值之外什么也没有。

>>> max(iter([]) or 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: max() arg is an empty sequence

答案 1 :(得分:8)

在3.4以上的Python版本中,您可以使用itertools.chain()向可能为空的序列添加另一个值。这将处理任何空的iterable,但请注意,它与提供default参数不完全相同,因为总是包含额外的值:

>>> from itertools import chain
>>> max(chain([42], []))
42

但是在Python 3.4中,如果序列不为空,则忽略默认值:

>>> max([3], default=42)
3

答案 2 :(得分:1)

_DEFAULT = object()

def max_default(*args, **kwargs):
    """
    Adds support for "default" keyword argument when iterable is empty.
    Works for any iterable, any default value, and any Python version (versions >= 3.4
    support "default" parameter natively).

    Default keyword used only when iterable is empty:

    >>> max_default([], default=42)
    42

    >>> max_default([3], default=42)
    3

    All original functionality is preserved:

    >>> max_default([])
    Traceback (most recent call last):
    ValueError: max() arg is an empty sequence

    >>> max_default(3, 42)
    42
    """

    default = kwargs.pop('default', _DEFAULT)
    try:
        return max(*args, **kwargs)
    except ValueError:
        if default is _DEFAULT:
            raise
        return default

奖金:

def min_default(*args, **kwargs):
    """
    Adds support for "default" keyword argument when iterable is empty.
    Works for any iterable, any default value, and any Python version (versions >= 3.4
    support "default" parameter natively).

    Default keyword used only when iterable is empty:

    >>> min_default([], default=42)
    42

    >>> min_default([3], default=42)
    3

    All original functionality is preserved:

    >>> min_default([])
    Traceback (most recent call last):
    ValueError: min() arg is an empty sequence

    >>> min_default(3, 42)
    3
    """

    default = kwargs.pop('default', _DEFAULT)
    try:
        return min(*args, **kwargs)
    except ValueError:
        if default is _DEFAULT:
            raise
        return default

答案 3 :(得分:0)

空序列的最大值&#34;应该&#34;是一个无限小的东西,无论序列的元素有什么类型。不幸的是,(1)使用空序列,您无法分辨元素的含义,(2)例如,Python中没有最负的整数。

因此,如果您希望在这种情况下做一些合理的事情,您需要帮助max。在Python的最新版本中,default有一个max参数(在我看来这是一个误导性的名称,但没关系),如果你传入一个空序列,它将被使用。在旧版本中,您只需要确保传入的序列不是空的 - 例如,通过or使用包含您希望在其中使用的值的单个序列情况下。

[在发布之后很久就被编辑了,因为Yaakov Belch在评论中指出我已经写过&#34;无限大&#34;我应该写的地方&#34;无限小&#34;。]

答案 4 :(得分:0)

考虑到上面的所有评论,它可以是这样的包装:

def max_safe(*args, **kwargs):
    """
    Returns max element of an iterable.

    Adds a `default` keyword for any version of python that do not support it
    """
    if sys.version_info < (3, 4):  # `default` supported since 3.4
        if len(args) == 1:
            arg = args[0]
            if 'default' in kwargs:
                default = kwargs.pop('default')
                if not arg:
                    return default

                # https://stackoverflow.com/questions/36157995#comment59954203_36158079
                arg = list(arg)
                if not arg:
                    return default

                # if the `arg` was an iterator, it's exhausted already
                # so use a new list instead
                return max(arg, **kwargs)

    return max(*args, **kwargs)

答案 5 :(得分:0)

另一种解决方案是使用三元运算符:

nums = []
max_val = max(nums) if nums else 0

max val = max(iter(nums) if nums else [0])

答案 6 :(得分:0)

可以创建简单的lambda来做到这一点:

begin_date,
wk_nmbr_begin,
end_date,
wk_nmbr_end,

您可以这样称呼:
get_max = lambda val_list: max([ val for val in val_list if val is not None ]) if val_list else None