On 24 December 2012 04:42, eryksun <eryk...@gmail.com> wrote: > On Sat, Dec 22, 2012 at 12:57 PM, Oscar Benjamin > <oscar.j.benja...@gmail.com> wrote: >>>> >>>> def make_int(obj): >>>> '''Coerce str, float and int to int without rounding error >>>> Accepts strings like '4.0' but not '4.1' >>>> ''' >>>> fnum = float('%s' % obj) >>>> inum = int(fnum) >>>> assert inum == fnum >>>> return inum >>> >>> Well, that function is dangerously wrong. In no particular order, >>> I can find four bugs and one design flaw. >> >> I expected someone to object to this function. I had hoped that they >> might also offer an improved version, though. I can't see a good way >> to do this without special casing the treatment of some or other type >> (the obvious one being str). > > Strings don't implement __int__ or __trunc__; they aren't numbers, so > why not special case them?
I hadn't realised that. Does the int(obj) function use isinstance(obj, str) under the hood? > You can parse strings with obj = > Decimal(obj) (this uses a regex). Then for all inputs set inum = > int(obj) and raise ValueError if inum != obj. It had occurred to me that this would be the obvious fix for the issue with large numbers. The result is: from decimal import Decimal def int_decimal(x): if isinstance(x, str): x = Decimal(x) ix = int(x) if ix != x: raise ValueError('Not an integer: %s' % x) return ix Probably what I more often want, though, is a function that simply refuses to handle real-valued types as inputs. That way if a float sneaks in I can choose the appropriate rounding function (or bug fix) at the source of the number. I'm not sure what's the best way to detect real-valued types. At least for the stdlib using the numbers module works: from numbers import Integral def int_(x): if not isinstance(x, (Integral, str)): raise TypeError('Need Integral: use round() or trunc()') return int(x) Oscar _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor