[Python-Dev] Passing floats to "i" parser marker
M.-A. Lemburg
mal@lemburg.com
Wed, 05 Feb 2003 15:41:05 +0100
Guido van Rossum wrote:
>>I must have missed something (again). Where was this discussed in
>>public ?
>
>
> The problem (and my opinion) has come up here on and off many times.
Hmm, I must have been on vacation then :-)
>>I've read a quote from Guido on the SF tracker:
>>"""
>>This is an age-old problem that crops up whenever "i"
>>and similar format codes are used.
>>
>>The problem is that on the one hand you want "i" to
>>accept other int-ish types that have an __int__ method. But on the
>>other hand you don't want it to accept float, which also has
>>an __int__ method. Or other float-ish types.
>>
>>I think the "i" format code has to be fixed, but I'm
>>not sure how -- maybe as a start it would be sufficient to test
>>explicitly for float and its subclasses and reject those.
>>That would still allow 3rd party float-ish classes that
>>implement __int__, but that's not so important.
>>"""
>>
>>I tend to *not* go conform with this opinion. If a type
>>implements __int__ then it should be accepted whereever
>>"i" is used. If the type feels that this usage is not
>>ideal, then the *type* should issue the warning or
>>TypeError, not the getargs.c implementation.
>
> Since all the type knows is that it's __int__ method is called, not
> that this is in the context of getargs.c, how could it protest in this
> case without protesting about all calls to int()?
But that's the point: "i" should work just like int() does
w/r to the __int__ slot and it does, so nothing is broken
which would need fixing.
IMHO, the right way to fix what you think is broken is by introducing
a new parser marker with your new semantics. Then use that parser
marker whereever it is found meaningful.
> The problem is really with the semantic definition of int(). There
> should have been two different functions: one to convert an int from
> some other representation to a real int, and one to truncate a float
> or similar number to an int, losing information. (The latter actually
> requires several, or a way to specify the rounding mode.
> Unfortunately round() and math.floor()/ceil() can't be used since
> these return floats themselves.)
>
> Fixing this would require a much larger change to the language, with
> much more backwards incompatibilities to worry about; changing "i"
> etc. to explicitly refuse float is a band-aid that catches most of the
> cases.
The problem is that your change propogates to all third-party
extensions as well and that's not desirable in all cases. IMHO,
it is not even desirable for all cases in the Python interpreter
(see below).
> By far the majority of types that implement __int__ represent int-like
> data; only floats and rationals use __int__ for losing information.
> That's why the above solution was chosen.
I'm sure that all numeric-like types implement __int__ for
the sake of being compatible to int().
>>Apart from this, the change is going to break tons of code,
>>once the TypeError is enforced and due to the dynamic
>>nature of Python a single release cycle will not be
>>enough to catch all places where an explicit int()
>>would be required...
>
> We'll change to a TypeError when we are confident that it won't break
> too much code.
>
> Why do you think so much will break? In Python 2.2, you can write
>
> a = range(10)
> a.insert(3.14, 0)
>
> and it will insert a 0 at position 3. This is undocumented. Do you
> really think anyone in the world willfully uses this?
No, this is one spot where the new parser marker would fit
well. Still, even in this case I think that passing
floats to "i" is perfectly OK, namely in all those cases
where no loss of data occurs, e.g. passing 13.0 to "i"
should be accepted as 13.
>>Which makes me think: int() started
>>to return longs a few months ago -- we don't even have
>>a cast which would raise an OverlfowError in case
>>the conversion to int is not possible.
>
> Why would you need one (except in C code, where "i" is such a cast)?
For exactly this case -- to make sure that "i" doesn't
overflow when receiving the return value from int().
> In the future, the difference between int and long will disappear
> completely.
>
>>Of course, int()
>>would return a long and then the "i" parser marker
>>implementation would complain, but that may be too late, e.g.
>>in the case where you pass the data over the wire or
>>store it in a file for later processing.
>
> YAGNI.
I wasn't proposing anything in the above paragraph...
what does YAGNI apply to here ?
--
Marc-Andre Lemburg
CEO eGenix.com Software GmbH
_______________________________________________________________________
eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,...
Python Consulting: http://www.egenix.com/
Python Software: http://www.egenix.com/files/python/