Python 空列表的安全 max() 函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36157995/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
A safe max() function for empty lists
提问by Alexander McFarlane
Evaluating,
评估,
max_val = max(a)
will cause the error,
会导致错误,
ValueError: max() arg is an empty sequence
Is there a better way of safeguarding against this error other than a try
, except
catch?
除了 a try
, except
catch之外,还有没有更好的方法来防止这个错误?
a = []
try:
max_val = max(a)
except ValueError:
max_val = default
回答by falsetru
In Python 3.4+, you can use default
keyword argument:
在 Python 3.4+ 中,您可以使用default
关键字参数:
>>> max([], default=99)
99
In lower version, you can use or
:
在较低版本中,您可以使用or
:
>>> max([] or [99])
99
NOTE: The second approach does not work for all iterables. especially for iterator that yield nothing but considered truth value.
注意:第二种方法不适用于所有可迭代对象。特别是对于只产生被认为是真值的迭代器。
>>> max(iter([]) or 0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: max() arg is an empty sequence
回答by Duncan
In versions of Python older than 3.4 you can use itertools.chain()
to add another value to the possibly empty sequence. This will handle any empty iterable but note that it is not precisely the same as supplying the default
argument as the extra value is always included:
在 3.4 之前的 Python 版本中,您可以使用itertools.chain()
向可能为空的序列添加另一个值。这将处理任何空的可迭代对象,但请注意,它与提供default
参数并不完全相同,因为总是包含额外的值:
>>> from itertools import chain
>>> max(chain([42], []))
42
But in Python 3.4, the default is ignored if the sequence isn't empty:
但是在 Python 3.4 中,如果序列不为空,则默认值将被忽略:
>>> max([3], default=42)
3
回答by Kurohige
Another solution could be by using ternary operators:
另一种解决方案是使用三元运算符:
nums = []
max_val = max(nums) if nums else 0
or
或者
max val = max(iter(nums) if nums else [0])
回答by Milo
_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
Bonus:
奖金:
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
回答by Zeeshan
Can create simple lambda to do this:
可以创建简单的 lambda 来做到这一点:
get_max = lambda val_list: max([ val for val in val_list if val is not None ]) if val_list else None
You can call it this way:get_max(your_list)
你可以这样称呼它:get_max(your_list)
回答by tsionyx
Considering all the comments above it can be a wrapper like this:
考虑到上面的所有评论,它可以是这样的包装器:
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)
回答by Gareth McCaughan
The max of an empty sequence "should" be an infinitely small thing of whatever type the elements of the sequence have. Unfortunately, (1) with an empty sequence you can't tell what type the elements were meant to have and (2) there is, e.g., no such thing as the most-negative integer in Python.
空序列的最大值“应该”是序列元素具有的任何类型的无限小东西。不幸的是,(1) 对于一个空序列,您无法判断元素的类型是什么,并且 (2) 例如,在 Python 中没有最负整数这样的东西。
So you need to help max
out if you want it to do something sensible in this case. In recent versions of Python there is a default
argument to max
(which seems to me a misleading name, but never mind) which will be used if you pass in an empty sequence. In older versions you will just have to make sure the sequence you pass in isn't empty -- e.g., by or
ing it with a singleton sequence containing the value you'd like to use in that case.
因此max
,如果您希望它在这种情况下做一些明智的事情,则需要提供帮助。在 Python 的最新版本中,有一个default
参数 to max
(在我看来是一个误导性的名称,但没关系),如果您传入一个空序列,它将被使用。在旧版本中,您只需要确保传入的序列不是空的——例如,通过or
使用包含您在这种情况下要使用的值的单例序列对其进行 ing。
[EDITED long after posting because Yaakov Belch kindly pointed out in comments that I'd written "infinitely large" where I should have written "infinitely small".]
[发布后很长时间编辑,因为 Yaakov Belch 在评论中友好地指出我写了“无限大”,而我应该写“无限小”。]