[Python-Dev] Change in Python 3's "round" behavior

2018-09-26 Thread jab
I recently found out about Python 3's round-to-even change (via
https://github.com/cosmologicon/pywat!) and am having trouble finding
where that change was discussed.

I did find the revealingly-invalid bug report
https://bugs.python.org/issue32956 ("python 3 round bug"), so I asked
there, but wanted to invite anyone else on this list who might be
interested to help. If interested, please see the comments there
(copy/pasted below for convenience), and +nosy or comment on that
issue.

Thanks!

Joshua Bronson added the comment:

This was so surprising to me that I had to check some other languages
that I had handy. It turns out that not one of JavaScript, Ruby, Perl,
C++, Java, Go, or Rust agrees with Python. In fact they all agreed
with one another that 2.5 should round to 3. Examples below.

I understand from
https://github.com/cosmologicon/pywat/pull/40#discussion_r219962259
that "to always round up... can theoretically skew the data" but it's
not clear why that's a good enough reason to differ from the "round"
function in all these other languages (as opposed to e.g. offering
this alternative behavior in some additional "round_unskewed"
function).

I assume the rationale for having Python 3's "round" differ from that
of so many other languages was written down when this decision was
made, but I searched and couldn't find it. Could anyone link to it in
a comment here?

And would it be worth including rationale and a larger callout in the
https://docs.python.org/3/library/functions.html#round docs? The
documentation of this behavior is a bit buried among other things, and
the rationale for it is missing entirely.


$ node -e 'console.log(Math.round(2.5))'
3

$ ruby -e 'puts (2.5).round()'
3

$ perl -e 'use Math::Round; print round(2.5)'
3

$ cat test_round.cpp
#include 
#include 
int main(void) {
  printf("%f\n", round(2.5));
}
$ g++ test_round.cpp && ./a.out
3.00

$ cat TestRound.java
class TestRound {
  public static void main(String[] args) {
System.out.println(Math.round(2.5));
  }
}
$ javac TestRound.java && java TestRound
3

$ cat test_round.go
package main
import "fmt"
import "math"
func main() {
fmt.Println(math.Round(2.5))
}
$ go build test_round.go && ./test_round
3

$ cat test_round.rs
fn main() {
  println!("{}", (2.5_f64).round());
}
$ rustc test_round.rs && ./test_round
3


Serhiy Storchaka added the comment:

See the discussion on the Python-Dev mailing list:
https://mail.python.org/pipermail/python-dev/2008-January/075863.html.

For C look at the rint() function. It is a common knowledge that
rounding half-to-even is what users want in most cases, but it is a
tiny bit more expensive in C. In Python the additional cost of such
rounding is insignificant.


Joshua Bronson added the comment:

Thanks Serhiy, I read the Python-Dev thread you linked to, but that
doesn't resolve the issues:

- Its topic is Python 2.6 (where this behavior does not occur) rather
than Python 3 (where it does).

- A few messages into the thread Guido does address Python 3, but in
fact says "I think the consensus is against round-to-even in 3.0" (see
https://mail.python.org/pipermail/python-dev/2008-January/075897.html).

- There is no discussion of the fact that this behavior differs from
the function named "round" in all the other programming languages I
mentioned, and whether it would therefore be better exposed as an
additional function (e.g. "round_to_even" or "round_unbiased", and in
the math or statistics package rather than builtins). Surprisingly,
Excel is the only other programming environment I saw discussed in the
thread. (And round(2.5) == 3 there.)

So that all suggests there must be some other thread or issue where
this change for Python 3 have been discussed, but I looked again and
could not find it.

The C "rint" example you gave just seems to prove the point that this
behavior should have a distinct name from "round".

Regarding:
> It is a common knowledge that rounding half-to-even is what users want in 
> most cases

I don't think that's common knowledge; seems like citation needed?
Based on all the other languages where this differs (not to mention
Python 2), it's not clear users would want Python 3 to be the only
different one. And this is definitely a surprise for the majority of
programmers, whose experience with "round" is how it works everywhere
else. (This is making it into pywat after all:
https://github.com/cosmologicon/pywat/pull/40)

I can submit a PR for at least updating the docs about this (as per my
previous comment) if that would be welcomed.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Intended Usage of collections.abc for Custom Collections

2015-10-28 Thread jab
On Wed, Oct 28, 2015 at 1:16 PM, Brett Cannon  wrote:

> On Wed, 28 Oct 2015 at 08:47  wrote:
>
>> Dear Python-Dev,
>>
>> I am the author of bidict, a bidirectional map implementation for Python.
>> A user recently filed a bug that bidict should be a subclass of dict, so
>> that isinstance(mybidict, dict) would return True. I replied that the user
>> should instead use isinstance(mybidict, collections.abc.Mapping), which
>> does already return True, and is more polymorphic to boot.
>>
>
> I would argue that chances are they don't need isinstance() in either
> case. :)
>
>
>> But before I put the issue to bed, I want to make sure I'm correctly
>> understanding the intended usage of collections.abc, as well as any
>> relevant interfaces I'm not currently using (collections.UserDict?
>> __subclasshook__?), since the documentation leaves me with some doubt.
>> Could any collections experts on this list please confirm whether bidict is
>> implemented as the language intends it should be?
>>
>
> ABCs are meant to make sure you implement key methods for an
> interface/protocol. So in the case of collections.abc.Mapping, it's to make
> sure you implement __getitem__. In exchange for subclassing the ABC you
> also gain some methods for free like get(). So you subclass an ABC because
> you want your object to be acceptable in any code that expects an object
> that implements that interface/protocol and you want the help ABCs provide
> in making sure you don't accidentally miss some key method.
>
> Subclassing a concrete implementation of the Mapping ABC -- which is what
> dict is -- should be done if it is beneficial to you, but not simply to
> satisfy an isinstance() check. I think the ABC registration is the right
> thing to do and the user requesting the dict subclass should actually be
> doing what you suggested and testing for the interface/protocol and not the
> concrete implementation.
>
> And if you want another way to hit this point home, with type hints people
> should only be expecting abstract types like typing.Mapping as input:
> https://docs.python.org/3/library/typing.html#typing.Mapping .
> Restricting yourself to only a dict locks out other completely viable types
> that implement the mapping interface/protocol. Much like working with data,
> you should be as flexible as possible on your inputs (e.g., specifying
> typing.Mapping as the parameter type), but as strict as possible on the
> return type (.e.g, specifying dict/typing.Dict as the return type).
>
> I honestly would want to know why the user cares about an isinstance()
> check to begin with since they might want to go with a try/except when
> using the object how they want it to be and erroring out if they get passed
> an object that doesn't quack like a dict thanks to duck typing.
>
> -Brett
>

Thanks very much for the thorough and thoughtful reply. I'll take this as
authoritative approval of the current design, barring any further
recommendations to the contrary.

As for the isinstance check, it turned out that this wasn't actually in the
user's code; the offending code is actually in the pandas library, which he
was using. I just submitted a PR there in case anyone is interested:
https://github.com/pydata/pandas/pull/11461

Thanks again for making my first experience on this list so positive.

-jab
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Intended Usage of collections.abc for Custom Collections

2015-10-28 Thread jab
Dear Python-Dev,

I am the author of bidict, a bidirectional map implementation for Python. A
user recently filed a bug that bidict should be a subclass of dict, so that
isinstance(mybidict, dict) would return True. I replied that the user
should instead use isinstance(mybidict, collections.abc.Mapping), which
does already return True, and is more polymorphic to boot.

But before I put the issue to bed, I want to make sure I'm correctly
understanding the intended usage of collections.abc, as well as any
relevant interfaces I'm not currently using (collections.UserDict?
__subclasshook__?), since the documentation leaves me with some doubt.
Could any collections experts on this list please confirm whether bidict is
implemented as the language intends it should be?

Some quick references:
https://bidict.readthedocs.org/en/latest/other-bidict-types.html#bidict-type-hierarchy
https://github.com/jab/bidict/blob/master/bidict/_bidict.py

I would be happy to try to capture what I learn from this thread and write
up a guide for collections library authors in the future, or otherwise pay
your help forward however I can.

Thanks and best wishes.

-jab
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com