@@ -426,15 +426,39 @@ async def map(
426426 yield await result
427427
428428
429- __MAX_DEFAULT = Sentinel ("<no default>" )
429+ __MIN_MAX_DEFAULT = Sentinel ("<no default>" )
430430
431431
432+ @overload
433+ async def max (iterable : AnyIterable [LT ], * , key : None = ...) -> LT :
434+ ...
435+
436+
437+ @overload
432438async def max (
433- iterable : AnyIterable [LT ],
439+ iterable : AnyIterable [LT ], * , key : None = ..., default : T
440+ ) -> Union [LT , T ]:
441+ ...
442+
443+
444+ @overload
445+ async def max (iterable : AnyIterable [T1 ], * , key : Callable [[T1 ], LT ] = ...) -> T1 :
446+ ...
447+
448+
449+ @overload
450+ async def max (
451+ iterable : AnyIterable [T1 ], * , key : Callable [[T1 ], LT ] = ..., default : T2
452+ ) -> Union [T1 , T2 ]:
453+ ...
454+
455+
456+ async def max (
457+ iterable : AnyIterable [Any ],
434458 * ,
435- key : Optional [Callable [[LT ], Any ]] = None ,
436- default : LT = __MAX_DEFAULT , # type: ignore
437- ) -> LT :
459+ key : Optional [Callable [[Any ], Any ]] = None ,
460+ default : Any = __MIN_MAX_DEFAULT ,
461+ ) -> Any :
438462 """
439463 Return the largest item from an (async) iterable or from two or more values
440464
@@ -452,33 +476,39 @@ async def max(
452476 as it does not benefit from being ``async``.
453477 Use the builtin :py:func:`max` function instead.
454478 """
455- async with ScopedIter (iterable ) as item_iter :
456- best = await anext (item_iter , default = __MAX_DEFAULT )
457- if best is __MAX_DEFAULT :
458- if default is __MAX_DEFAULT :
459- raise ValueError ("max() arg is an empty sequence" )
460- return default
461- if key is None :
462- async for item in item_iter :
463- if item > best :
464- best = item
465- else :
466- key = _awaitify (key )
467- best_key = await key (best )
468- async for item in item_iter :
469- item_key = await key (item )
470- if item_key > best_key :
471- best = item
472- best_key = item_key
473- return best
479+ return await _min_max (iterable , key , True , default )
480+
474481
482+ @overload
483+ async def min (iterable : AnyIterable [LT ], * , key : None = ...) -> LT :
484+ ...
475485
486+
487+ @overload
476488async def min (
477- iterable : AnyIterable [LT ],
489+ iterable : AnyIterable [LT ], * , key : None = ..., default : T
490+ ) -> Union [LT , T ]:
491+ ...
492+
493+
494+ @overload
495+ async def min (iterable : AnyIterable [T1 ], * , key : Callable [[T1 ], LT ] = ...) -> T1 :
496+ ...
497+
498+
499+ @overload
500+ async def min (
501+ iterable : AnyIterable [T1 ], * , key : Callable [[T1 ], LT ] = ..., default : T2
502+ ) -> Union [T1 , T2 ]:
503+ ...
504+
505+
506+ async def min (
507+ iterable : AnyIterable [Any ],
478508 * ,
479- key : Optional [Callable [[LT ], Any ]] = None ,
480- default : LT = __MAX_DEFAULT , # type: ignore
481- ) -> LT :
509+ key : Optional [Callable [[Any ], Any ]] = None ,
510+ default : Any = __MIN_MAX_DEFAULT ,
511+ ) -> Any :
482512 """
483513 Return the smallest item from an (async) iterable or from two or more values
484514
@@ -496,22 +526,37 @@ async def min(
496526 as it does not benefit from being ``async``.
497527 Use the builtin :py:func:`min` function instead.
498528 """
529+ return await _min_max (iterable , key , False , default )
530+
531+
532+ async def _min_max (
533+ iterable : AnyIterable [LT ],
534+ key : Optional [Callable [[LT ], Any ]],
535+ invert : bool ,
536+ default : LT = __MIN_MAX_DEFAULT , # type: ignore
537+ ) -> LT :
538+ """
539+ Implementation of ``min``/``max``
540+
541+ :param invert: compute ``max`` if ``True`` and ``min`` otherwise
542+ """
499543 async with ScopedIter (iterable ) as item_iter :
500- best = await anext (item_iter , default = __MAX_DEFAULT )
501- if best is __MAX_DEFAULT :
502- if default is __MAX_DEFAULT :
503- raise ValueError ("min() arg is an empty sequence" )
544+ best = await anext (item_iter , default = __MIN_MAX_DEFAULT )
545+ if best is __MIN_MAX_DEFAULT :
546+ if default is __MIN_MAX_DEFAULT :
547+ name = "max" if invert else "min"
548+ raise ValueError (f"{ name } () arg is an empty sequence" )
504549 return default
505550 if key is None :
506551 async for item in item_iter :
507- if item < best :
552+ if invert ^ ( item < best ) :
508553 best = item
509554 else :
510555 key = _awaitify (key )
511556 best_key = await key (best )
512557 async for item in item_iter :
513558 item_key = await key (item )
514- if item_key < best_key :
559+ if invert ^ ( item_key < best_key ) :
515560 best = item
516561 best_key = item_key
517562 return best
0 commit comments