@ruud Anyway, if you want to support also default
, I think that, before you return it, you should transform it to a tuple
and check if its length is 2. Otherwise, an error should be raised.
Obviously not as evident as you presume, from the reactions to ypur example.
Given the âtwo different placements of NaNâ example, I would think its the fault of trying to find the minimum of results containing NaNâs. I would be at fault for not accounting for NaNâs. Ignoring them, or any other action could depend on circumstance - whâs to say that an arbitrary resolution is th one needed?
It might be better still to raise an exception unless an option is given to state how NaNâs should be treated - at least they wonât silently be ignored.
@Paddy3118 Please discuss this here:
https://discuss.python.org/t/2868
Marco, point us at official Python documentation that documents what min
and max are supposed to do when passed values that donât provide a total
order, and if that documented behaviour is different from what the
functions actually do, then we will conceed that it is a bug.
There are at least three different things that min(0, NAN) could do:
- propogate the NAN (return a NAN)
- ignore the NAN (return 0)
- raise an exception
and no consensus on what it should do. At least half our users will
consider your version to be âbuggyâ since it doesnât match their
expectations. You donât get to unilaterally decide what is correct and
what is buggy.
If you want to change this, you will need to write a PEP. You should
consider the two different versions of min/max that the IEEE-754
standard specifies, plus any other versions that others may desire
(such as a version which raises an exception).
It isnât enough to specify the behaviour with NANs, there are an
infinite number of ways a data set can fail to provide a total order.
For instance, dominance heirarchies are often not a total order, for
example Rock Paper Scissors:
Rock > Scissors
Scissors > Paper
Paper > Rock
max(Rock, Paper, Scissors) should do what?
Unless you are prepared to write a PEP, thereâs no point in you
continuing this argument. There is no agreement on what the âcorrectâ
behaviour is, so any version we provide will surprise some people. The
best we can do is explicitly document that the behaviour for data sets
that donât define a total order will be implementation-defined and
therefore we make no promise about what will happen.
(The fact that min and max currently ignore NANs that arenât in the
first position is an accident, not an intentional behaviour.)
Paul: âundefined behaviourâ has special meaning to C programmers which
it doesnât have to other language programmers. Given the special place C
has in the programming ecosystem, I prefer to honour their definition,
and use âimplementation-defined behaviourâ for what we are talking about
here.
@steven.daprano *sigh* please discuss it here⌠and please read first the posts:
https://discuss.python.org/t/2868
Thanks, thatâs a good point. I do like the connotations of Câs âundefined behaviourâ (in general, but in this discussion in particular) but if itâs not a familiar idea to people in general, itâs probably just confusing the discussion. Iâll keep this in mind.
As a reminder to people, posts can be flagged to the admins to handle potential PSF Code of Conduct issues so they can be dealt with appropriately.
Please Mark, âeven a baby can do itâ and similar phrases is a standard
English idiom for âits easyâ. Its no more disrespectful than if Marco
had said âIt is easy to understand that codeâ.
It is not an aggression, not even a microagression or a nanoaggression,
although I suppose the mere fact that Marco is disagreeing with me makes
it a picoaggression. I think I can cope with mere disagreement wink
Can we please assume good faith and not be so touchy that everyone has
to walk around on eggshells for fear of being banned for the most
innocuous comment?
It should not only restrict to find min max numbers, other functionalities also include e.g comparisons of min max of two lists, string lengths etc. It will helpful in spatial data as well.
I donât want this thread to devolve into a CoC discussion (or really get into one period), but the issues went beyond just the âbabyâ comment. And in regards to that specific comment, it could still be insulting to someone who actually didnât find it easy to understand and so feels like a put-down. Simply saying âI think itâs easy to understandâ would have been enough to get the point across and not risk insulting someone accidentally.
Thereâs something of a parallel with the built-in function divmod
here. Thereâs an excellent reason for having divmod
available, namely that itâs common to want to compute both a // b
and a % b
as part of some algorithm, and computing them separately is needlessly inefficient: in current CPython, a // b
(for a
and b
of type int
) computes both the quotient and the remainder, then throws the remainder away and returns the quotient. Similarly for a % b
. So by evaluating a // b
and a % b
separately youâre computing the quotient and the remainder twice each instead of once. divmod
solves this inefficiency.
Nevertheless, Iâve always found divmod
oddly unsatisfying in practice, and despite writing a lot of integer-based algorithmic code, I almost never use divmod
, and I rarely see it used in other peopleâs code. Part of the issue is readability: if I have an expression that uses both a % b
and a // b
and I want to use divmod
for efficiency, I have to introduce a separate statement to call divmod(a, b)
and unpack the resulting tuple. I canât simply use divmod
directly in my expression without using it twice, which defeats the point. So my functional-style code becomes more procedural and a mite harder to read as a result, especially since a function call is being substituted for operators.
I donât know if we have, or can get, statistics on usage of builtins, but Iâd hazard a guess that divmod
is one of the least-used built-in functions. (To be clear, before anyone gets excited, I am not proposing that divmod
be deprecated, moved, or removed. It is what it is.)
I suspect minmax
would suffer from some of the same issues, though we donât have the operator versus function call aspect. I think it wouldnât get used as much as one might a priori expect. It might be useful to look at some before-and-after examples from real-world code to see to what extent readability is affected.
Thatâs not to say that minmax
wouldnât be useful, but in spite of min
and max
being builtins, I doubt that minmax
would be useful often enough to justify adding it to builtins. Which leaves us with the issue of figuring out where it does belong, and I donât have a good answer to that. math
, statistics
and itertools
seem like the obvious candidates. Of the three, Iâd probably go with math
: it bothers me a bit that minmax
, like min
and max
, wouldnât necessarily be specifically for numbers, which makes math
seem inappropriate, but we already have a precedent for putting a generic not-necessarily-numeric function in math
, in the form of math.prod
.
Out of idle curiosity how many of these statistical functions would there be that would benefit from a âcontinuousâ evaluation of their value? (Ignoring the discussion on NAN for a moment)
Would there be value in a function that would evaluate a range of statistical values in a single live pass?
Min/Max
Sum
A//B
A%B
Possibly returning a tuple in the order that the functions were requested?