wake-up-neo.net

Eine sichere max () - Funktion für leere Listen

Auswerten,

max_val = max(a)

wird den Fehler verursachen,

ValueError: max() arg is an empty sequence

Gibt es einen besseren Schutz gegen diesen Fehler als eine try, except catch?

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

In Python 3.4 und höher können Sie das default-Schlüsselwortargument verwenden:

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

In der niedrigeren Version können Sie or verwenden:

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

HINWEIS: Der zweite Ansatz funktioniert nicht für alle Iterables. vor allem für Iteratoren, die nichts anderes ergeben als den betrachteten Wahrheitswert.

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

In älteren Python-Versionen als 3.4 können Sie itertools.chain() verwenden, um der möglicherweise leeren Sequenz einen weiteren Wert hinzuzufügen. Dies behandelt alle leeren Iterationen. Beachten Sie jedoch, dass es nicht genau dasselbe ist, als das Argument default anzugeben, da der zusätzliche Wert immer enthalten ist:

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

In Python 3.4 wird der Standardwert jedoch ignoriert, wenn die Sequenz nicht leer ist:

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

Eine andere Lösung könnte die Verwendung von ternären Operatoren sein:

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

oder

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

In Anbetracht aller obigen Kommentare kann es sich um einen Wrapper handeln:

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)
0
tsionyx

Das Maximum einer leeren Sequenz "sollte" eine unendlich kleine Sache sein, unabhängig von der Art der Elemente der Sequenz. Unglücklicherweise können Sie (1) mit einer leeren Sequenz nicht sagen, welchen Typ die Elemente haben sollen, und (2) gibt es beispielsweise keine negativste Ganzzahl in Python.

Sie müssen also max helfen, wenn Sie in diesem Fall etwas sinnvolles tun möchten. In den letzten Versionen von Python gibt es ein default-Argument für max (das scheint mir ein irreführender Name zu sein, aber egal), das verwendet wird, wenn Sie eine leere Sequenz übergeben. In älteren Versionen müssen Sie lediglich sicherstellen, dass die übergebene Sequenz nicht leer ist - beispielsweise durch oring mit einer Singleton-Sequenz, die den Wert enthält, den Sie in diesem Fall verwenden möchten.

[Lange nach dem Posting herausgegeben, weil Yaakov Belch in Kommentaren freundlich darauf hingewiesen hatte, dass ich "unendlich groß" geschrieben habe, wo ich "unendlich klein" hätte schreiben sollen.]

0