61 lines
1.6 KiB
Python
61 lines
1.6 KiB
Python
# tag::MYMAX_TYPES[]
|
|
from typing import Protocol, Any, TypeVar, overload, Callable, Iterable, Union
|
|
|
|
class SupportsLessThan(Protocol):
|
|
def __lt__(self, other: Any) -> bool: ...
|
|
|
|
T = TypeVar('T')
|
|
LT = TypeVar('LT', bound=SupportsLessThan)
|
|
DT = TypeVar('DT')
|
|
|
|
MISSING = object()
|
|
EMPTY_MSG = 'max() arg is an empty sequence'
|
|
|
|
@overload
|
|
def max(__arg1: LT, __arg2: LT, *_args: LT, key: None = ...) -> LT:
|
|
...
|
|
@overload
|
|
def max(__arg1: T, __arg2: T, *_args: T, key: Callable[[T], LT]) -> T:
|
|
...
|
|
@overload
|
|
def max(__iterable: Iterable[LT], *, key: None = ...) -> LT:
|
|
...
|
|
@overload
|
|
def max(__iterable: Iterable[T], *, key: Callable[[T], LT]) -> T:
|
|
...
|
|
@overload
|
|
def max(__iterable: Iterable[LT], *, key: None = ...,
|
|
default: DT) -> Union[LT, DT]:
|
|
...
|
|
@overload
|
|
def max(__iterable: Iterable[T], *, key: Callable[[T], LT],
|
|
default: DT) -> Union[T, DT]:
|
|
...
|
|
# end::MYMAX_TYPES[]
|
|
# tag::MYMAX[]
|
|
def max(first, *args, key=None, default=MISSING):
|
|
if args:
|
|
series = args
|
|
candidate = first
|
|
else:
|
|
series = iter(first)
|
|
try:
|
|
candidate = next(series)
|
|
except StopIteration:
|
|
if default is not MISSING:
|
|
return default
|
|
raise ValueError(EMPTY_MSG) from None
|
|
if key is None:
|
|
for current in series:
|
|
if candidate < current:
|
|
candidate = current
|
|
else:
|
|
candidate_key = key(candidate)
|
|
for current in series:
|
|
current_key = key(current)
|
|
if candidate_key < current_key:
|
|
candidate = current
|
|
candidate_key = current_key
|
|
return candidate
|
|
# end::MYMAX[]
|