Tell me please try to understand the implementation of the MIN / MAX function.
I have the following thoughts:

If the input is given to the list with numbers and (Len! = 1) – Sort List
tmp.sort (key = key) Return TMP [0]
Select the first element (min) or last (max)

If the text is given to the input (it turns out that Len == 1) is a realized search for a smaller / longer letter
min_text = args [0] For i in args [0]: IF I & LT; min_text: MIN_TEXT = I. Return min_text

But if the consignment is served on the entrance –
[[1,2], [3, 4], [9, 0]], Key = lambda x : x [1]
then when checking for a length, it falls under Len == 1, and does not undergo realization.
Tell me, apparently I try to build a bike, how will it be more correct to implement such a function?
Answer 1, Authority 100%
If you want to repeat the implementation of the standard function max
(or min
, but there is almost the same, so I will tell about one max
), That’s a few considerations that need for this:

If the argument is one, then we consider it an object by which you can walk the cycle (ITERABLE). Such objects are lists, cortices, rows, generators and much more, so it is not necessary to consider lists separately from the rows.

If there are two or more arguments, then connect them to one list that is automatically ITERABLE.

A variable number of arguments can be accepted using
* Args
.
Taking into account all this, you can write the function approximately such:
def max2 (arg1, * args, key = lambda x: x):
# Arg1  & nbsp; first argument, args  & nbsp; list of second and subsequent arguments
IF Args:
# Passed several arguments  we combine everything in one list
ITERABLE = [ARG1] + LIST (ARGS)
ELSE:
# Passed one argument  & nbsp; believe that he is ITERABLE
Iterable = Arg1
# First as a maximum choose the first element
Result = Iterable [0]
# Walk out the rest of the elements
For item in Iterable [1:]:
IF KEY (Item) & GT; Key (Result):
Result = Item.
Return Result
As far as I can judge, it (within the framework of the applicability specified by me) corresponds to the standard implementation of Max
in Python:
& gt; & gt; & gt; MAX (3, 4, 5) == MAX2 (3, 4, 5)
True # 5.
& gt; & gt; & gt; max ([3, 4, 5]) == MAX2 ([3, 4, 5])
True # 5.
& gt; & gt; & gt; MAX ('ABC') == max2 ('abc')
True # 'C'
& gt; & gt; & gt; Max ([[1, 2], [3, 4], [9, 0]], Key = lambda x: x [1]) == Max2 ([[1, 2], [3, 4], [ 9, 0]], Key = lambda x: x [1])
True # [3, 4]
(But in this feature I have lowered the processing of empty lists and support for objects in which you cannot contact the index (generators, for example), so that this function is suitable only for educational purposes, and in real programs, use the usual Max
🙂
Here is a more accurate implementation (now it is no longer max
, but min
), but more complicated for understanding, so I write it separately. To maintain the processing of ITERABLEobjects, you will have to refuse to appeal to it on the index and set the first element more slyly.
def min2 (arg1, * args, default = none, key = lambda x: x):
IF Args:
# If we have a list of arguments, then not ceremony
# and start right away from the first element
Result = Arg1
Started = True.
ITERABLE = Args.
ELSE:
# If we are ITERABLE first argument, then
# Cecermony and start in the FOR cycle (this allows
# Get rid of appeal by index)
Result = Default.
Started = False
Iterable = Arg1
# We take place on the iterative object elements
For item in Iterable:
IF Not Started:
# If the first element does not exist yet,
# then put it
Result = Item.
Started = True.
Continue.
# If the previous element exists, then compare
If Key (Item) & LT; Key (Result):
Result = Item.
Return Result
This function corresponds to the native implementation in almost all cases known to me (except for one insignificant to the question min ([])
):
& gt; & gt; & gt; MIN ({5, 4, 3}) == min2 ({5, 4, 3})
True # 3.
& gt; & gt; & gt; MIN ([], default = 7) == min2 ([], default = 7)
True # 7; only in python 3
& gt; & gt; & gt; MIN (ABS (I) for i in Range (10.10)) == MIN2 (ABS (I) for i in Range (10.10))
True # 0.
Here, in contrast to a simpler previous implementation, no lists are not created, and there are only a few variables, therefore this implementation O (1) in memory (you can directly process many items without spending if you get the appropriate generator, For example Range
(XRANGE
in Python 2)). The cycle here is oneonly, therefore o (n) by steps, which matches the standard implementation (if you believe the comment JFS).
Answer 2, Authority 67%
Find a minimum / maximum using one linear algorithm for different types of input: both for lists with numbers and for strings and for the list of pairs:
def min_item (items, *, key = lambda x: x):
min_, * Items = Items
For item in Items:
If Key (Item) & LT; Key (min_):
min_ = item.
RETURN MIN_
Example:
& gt; & gt; & gt; min_item ([2, 1, 3])
1
& gt; & gt; & gt; MIN_IEM ("ABC")
'B'
& gt; & gt; & gt; min_item ([[1,2], [3, 4], [9, 0]], Key = Lambda X: X [1])
[9, 0]
Where syntax with the star is used to the first element from Collections get:
& gt; & gt; & gt; a, * b = [1, 2, 3]
& gt; & gt; & gt; Print (A, B)
1 [2, 3]
Sorted (Items, Key = Key) [0]
would work for all cases presented, but sorting based on comparisons requires o (n * log n)
operations, so a simple cycle is shown as an example of the implementation of min ()
using Linear (o (n)
) algorithm.
Standard Min / Max Functions Fasciner Presented by Min_Item ()
:

You can transfer several arguments:
& gt; & gt; & gt; min (1, 2, 3) 1

If you enter the empty, then the default value can be returned:
& gt; & gt; & gt; min ([], Default = 1) 1

Memory consumed does not depend on the number of transmitted elements (while implementing above uses
o (n)
additional memory – the more input, the greater memory is required)  You can optimize the algorithm to avoid the call
Key ()
several times for the same item.
Easy to adapt min_item ()
function so that it supports several arguments:
def min_item (first, * args, key = lambda x: x):
If not Args: # First Is An Iterable
First, * Args = First
For Arg in Args:
if key (arg) & lt; Key (FIRST):
First = Arg.
Return first
In this case, if one argument is transmitted (Len (Args) == 0
and therefore Not Args
Branch is performed), then behavior is identical to the first example. If several positional arguments are transmitted, then it is searched for at least among them:
& gt; & gt; & gt; min_item (2, 1, 3)
1
& gt; & gt; & gt; min_item ([2, 1, 3])
1
& gt; & gt; & gt; min_item ("ABC", Key = str.Lower)
'A'
To meet memory requirements, you can use iterators:
_ Sentinel = Object ()
Def Min (First, * Args, Key = Lambda X: X, Default = _sentinel):
If not Args: # First Is An Iterable
Args = iTer (First)
Try:
First = Next (Args)
Except Stopiteration: # Empty
If Default Is _sentinel:
Raise Valueerror ("MIN () Arg Is An Empty Sequence") from none
Return Default.
ELIF DEFAULT IS NOT _SENTINEL:
Raise Typeerror ("Cannot Specify A Default for Min () with Multiple Positional Arguments")
Min_Key = Key (First)
For Arg in Args:
K = Key (ARG)
if k & lt; MIN_KEY:
min_key = k.
First = Arg.
Return first
This feature behaves like Standard Min ()
Function .
_sentinel
Used to determine if Default
option is called when calling a function.
Key ()
The function is called only once for each element at the input.
This implementation of the min ()
function supports an arbitrary (final) number of input elements, without increasing consumed additional memory with incorporation growth.
Example:
& gt; & gt; & gt; MIN_ (Map (Len, File)) # Length of the shortest line in (possible large) file
& gt; & gt; & gt; min_ (1, 2, 3)
1
& gt; & gt; & gt; min_ (x * x for x in Range (10, 3))
0.
& gt; & gt; & gt; min ([])
Traceback (MOST Recent Call Last):
File "& lt; stdin & gt;", line 1, in & lt; module & gt;
Valueerror: min () Arg is an empty sequence
& gt; & gt; & gt; min ([], Default = 1)
1
Realization max ()
Extremely similar to & lt;
on & gt;
change.