[Python-ideas] "Exposing" `__min__` and `__max__`

Steven D'Aprano steve at pearwood.info
Wed Jun 27 10:27:01 EDT 2018


On Wed, Jun 27, 2018 at 06:52:14AM -0700, Michael Selik wrote:

> > > Have you ever written ``max(range(x))`` in production code?
> >
> > I have never written that.
> >
> > But I have written ``max(iterable)`` dozens of times, where iterable
> > could be a range object.
> >
> 
> My intent was to ask where a range was in fact passed into max, not merely
> where it could be. It'd be enlightening to see a complete, realistic
> example.

A complete, realistic example is as I said: you call max() on some 
object which you don't control, the caller does. You could be 
passed a list, or a set, or a bitset, a binary search tree, a range 
object, whatever the caller happens to pass to you.

If you control your own input, then this doesn't sound too interesting. 
You know when you will get a list, and you can call max() on it, and you 
know when you are passing yourself a tree, and you can give your own 
tree a max() method and call that.

But if you don't control your input, then this is a good way to delegate 
back to the unknown object of an unknown class which knows itself.

Currently max() and min() have no choice but to walk the entire data 
structure, even if the object already knows its own maximum and minimum 
values. That's wasteful.

An analogy: in Ruby, the equivalent of the len() built-in falls back on 
iteration as a last resort for any object which doesn't define a len 
method:


    size = 0
    for x in obj:
        size += 1
    return size


By this analogy, max() and min() currently are like that last-resort 
version of len(), except they do it for *every* object that can be 
iterated over even when there's no need.

Imagine that Python's len() always walked the entire iterable, from 
start to end, to count the length. Now suppose that you proposed 
adding a __len__ protocol so that objects that know their own length 
can report it quickly, and in response I argued that

    len(range(x))

was unrealistic and that there is no need for a __len__ method 
because we could just say 

    range(x).stop

instead. I don't think you would find that argument very persuasive, 
would you?



-- 
Steve


More information about the Python-ideas mailing list