There are no __min__
and __max__
special methods*. This is kind of a shame since range
has seen some pretty nice optimizations in Python 3. You can do this:
>>> 1000000000000 in range(1000000000000)
False
But don't try this unless you want to wait a long time:
>>> max(range(1000000000000))
However creating your own min
/max
functions is a pretty good idea, as suggested by Lærne.
Here is how I would do it. UPDATE: removed the dunder name __min__
in favor of _min
, as recommended by PEP 8:
Never invent such names; only use them as documented
Code:
from functools import wraps
oldmin = min
@wraps(oldmin)
def min(*args, **kwargs)
try:
v = oldmin(*args, **kwargs)
except Exception as err:
err = err
try:
arg, = args
v = arg._min()
except (AttributeError, ValueError):
raise err
try:
return v
except NameError:
raise ValueError('Something weird happened.')
I think this way is maybe a little bit better because it handles some corner cases the other answer hasn't considered.
Note that an iterable object with a _min
method will still be consumed by oldmin
as per usual, but the return value is overridden by the special method.
HOWEVER, if the _min
method requires the iterator to still be available for consumption, this will need to be tweaked because the iterator is getting consumed by oldmin
first.
Note also that if the __min
method is simply implemented by calling oldmin
, things will still work fine (even though the iterator was consumed; this is because oldmin
raises a ValueError
in this case).
* Such methods are often called "magic", but this is not the preferred terminology.