<div dir="ltr"><div>I do think there is some merit in being able to as easily as possible transition from something being, say list-backed, to a domain specific data structure that's more efficient.  If one wanted to go from a list to a minheap, it'd be nice just to change `x = []` to `x = Heap()` and have everything else "just work", without having to change all `min(x)`s to `x.min()`s, etc.  But trying to find places in production code where there is the special casing you described is (now) on the top of my priorities.</div><div><br></div>Outside of invariant-maintaining data structures though, I think the most compelling case I've come up with so far is that it could be implemented on certain types of generators, without having to generate the whole sequence.  (IMHO, they're neat side effects, but not very compelling by themselves):  <div><br></div><div>- __min__ and __max__ could be implemented on the range object, as calculating these are straightforward, and you wouldn't need to generate the entire sequence.  Passing an "un-listified" range to a function that accepts lists is somewhat common, I think.  The inefficiency is compounded if you generate the sequence multiple times, e.g.:</div><div><br></div><div><div><font face="monospace, monospace">    def get_err(iterable):</font></div><div><font face="monospace, monospace">        return max(iterable) - min(iterable)</font></div></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    x = range(10000)</font></div><div><font face="monospace, monospace">    get_err(x)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    # vs</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    x = list(range(10000))</font></div><div><font face="monospace, monospace">    get_err(x)</font></div><div><br></div><div>  Here, implementing __min__ and __max__ would make passing a range not just as fast as passing a "listified" range, but significantly faster.  But I think this is just a nice coincidence of exposing the special methods and by no means motivating by itself.</div><div><br></div><div>- There are also a few infinite generators in itertools where calling min() or max() on the generator will run forever, despite at least one of these being a clearly defined:</div><div><br></div><div><div><font face="monospace, monospace">    from itertools import count, cycle</font></div></div><div><font face="monospace, monospace"><br></font></div><div><div><font face="monospace, monospace">    gen = count(start=0, step=1)  # min=0, no max</font></div><div><font face="monospace, monospace">    # or</font></div><div>

<font face="monospace, monospace"><span style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">    gen = cycle([1,2,3])          # min=1, max=3</span><br></font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    print(min(gen))               # Will never terminate</font></div><div><br></div><div>  I'm even less sure about how often this would actually help than I am the range example. I don't envision many places where people are passing infinite generators to things expecting standard lists -- especially in light of the fact that calling min() or max() on them will prevent further execution.</div><div><br></div><div>Thanks for all the feedback, the search will continue :)</div><div><br></div><div><br></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jun 20, 2018 at 11:24 AM, Guido van Rossum <span dir="ltr"><<a href="mailto:guido@python.org" target="_blank">guido@python.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Finding more realistic use cases is key -- the actual spec is pretty obvious and doesn't worry me in terms of added language or implementation complexity.<br></div><div><br></div><div>I think just finding a data structure that should implement its own min/max funtionality (or maybe one of these, like heapq) is not enough motivation. You have to find code where such a data structure (let's say a Tree) is passed to some function that  also accepts, say, a list. Then that function would benefit from being able to call just `min(x)` rather than `x.min() if isinstance(x, Tree) else min(x)`. If whenever you have a Tree you know that you have a Tree (because it has other unique methods) then there's no burden for the user to call x.min().</div><div><br></div><div>--Guido<br></div></div><div class="HOEnZb"><div class="h5"><br><div class="gmail_quote"><div dir="ltr">On Wed, Jun 20, 2018 at 5:24 AM James Edwards <<a href="mailto:jheiv@jheiv.com" target="_blank">jheiv@jheiv.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">> 

<span style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Are there any builtins or std library classes that offer their own<span> </span></span><br style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial"><span style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">min()/max() methods?</span>

<div><span style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></div><div><span style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">My first instinct was heapq[1], since the way to access the min value is simply heap[0] (and I thought it could benefit from __min__) -- it's almost the perfect motivating example.  But as it stands, the module uses functions to operate directly on a standard list, so even if __min__ were exposed, min(heap) would still iterate over the entire list.</span></div><div><span style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></div><div><span style="font-size:12.8px">That being said, a heap <i>class</i> could take advantage of this, and provide a semantically consistent optimization.</span></div><div><br></div><div>I'm not sure how many examples will be found in stdlib, as I expect this optimization to be restricted to specialized container types like heaps, but I'll keep searching.</div><div><br></div><div><span style="font-size:12.8px">[1] <a href="https://docs.python.org/3.6/library/heapq.html" target="_blank">https://docs.python.org/3.6/<wbr>library/heapq.html</a></span><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jun 20, 2018 at 3:00 AM, Steven D'Aprano <span dir="ltr"><<a href="mailto:steve@pearwood.info" target="_blank">steve@pearwood.info</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span>On Wed, Jun 20, 2018 at 07:05:19AM +0300, Serhiy Storchaka wrote:<br>
> 19.06.18 22:18, James Edwards пише:<br>
> >I've only recently looked for these special methods, so that in and of <br>
> >itself may be the reason these methods aren't exposed, but I could think <br>
> >of objects that may wish to implement __min__ and __max__ themselves, <br>
> >for efficiency.<br>
> <br>
> There are two questions.<br>
> <br>
> 1. What to do with additional min() and max() arguments: key and default.<br>
<br>
</span>Since there are no reflected versions of min/max, there is no trouble <br>
with extra arguments. Just pass them through to the dunder:<br>
<br>
min(obj, key=x, default=y) => type(obj).__min__(key=x, default=y)<br>
<span><br>
<br>
> 2. Is the need of this feature large enough? Will the benefit for <br>
> special cases exceed the drawback of increasing implementation <br>
> complexity and slowing down common cases?<br>
<br>
</span>Reasonable questions, but I don't think that the cost of testing:<br>
<br>
    if hasattr(type(obj), '__min__')<br>
    # or equivalent<br>
<br>
is going to be very large. Amortized over O(N) comparisons, that's <br>
practically free :-)<br>
<br>
More important, I think, is the increase in API complexity. That's two <br>
more dunders to learn about.<br>
<br>
The first part is critical: is this useful enough to justify two more <br>
dunders? I think the answer is a definite Maybe. Or perhaps Maybe Not.<br>
<br>
I think that without at least one use-case in the standard library, <br>
perhaps we should hold off on this. Unless numpy arrays are important <br>
enough to justify this on their own?<br>
<br>
Are there any builtins or std library classes that offer their own <br>
min()/max() methods? If so, that would be good evidence that making this <br>
a dunder-based protocol has stdlib use-cases.<br>
<span class="m_-236690761877644572m_-1979635170932275478HOEnZb"><font color="#888888"><br>
<br>
<br>
-- <br>
Steve<br>
</font></span><div class="m_-236690761877644572m_-1979635170932275478HOEnZb"><div class="m_-236690761877644572m_-1979635170932275478h5">______________________________<wbr>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/<wbr>codeofconduct/</a><br>
</div></div></blockquote></div><br></div>
______________________________<wbr>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/<wbr>codeofconduct/</a><br>
</blockquote></div><br clear="all"><br></div></div><span class="HOEnZb"><font color="#888888">-- <br><div dir="ltr" class="m_-236690761877644572gmail_signature" data-smartmail="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</font></span></blockquote></div><br></div>