check if object is number

Steven Bethard steven.bethard at gmail.com
Fri Feb 11 17:41:43 EST 2005


George Sakkis wrote:
>>George Sakkis wrote:
>>
>>>"Steven Bethard" <steven.bethard at gmail.com> wrote in message
>>>news:gcidnb9g_ojxnpDfRVn-tA at comcast.com...
>>>
>>>>Is there a good way to determine if an object is a numeric type?
>>>
>>>In your example, what does your application consider to be numeric?
>>
>>Well, here's the basic code:
>>
>>def f(max=None):
>>     ...
>>     while max is None or n <= max:
>>         ...
>>         # complicated incrementing of n
>>
>>So for 'max', technically all I need is <= support.  However, the code
>>also depends on the fact that after incrementing 'n' enough, it will
>>eventually exceed 'max'.  Currently, ints, longs, floats, and Decimals
>>will all meet this behavior.  But I'd rather not specify only those 4
>>(e.g. with a typecheck), since someone could relatively easily create
>>their own new numeric type with the same behavior.  Do you know a better
>>way to test for this kind of behavior?
> 
> The problem is more conceptional rather than technical.

Yup.

> So what you're saying is that 3 <= "3.0" should not be allowed, but
> 3 <= SomeUserDefinedNumericClass(3) is ok, although your program knows
> nothing a priori about SomeUserDefinedNumericClass. The idea suggested
> before, try if "x+1" fails or not does not get you far; any class that
> overrides __add__ may fool this test:
> 
> class Dummy:
>     def __add__(self,other):
>         return 0

Right but by the same logic, we can fool protocols that are builtin to 
Python:

py> class C(object):
...     def __iter__(self):
...         return 0
...
py> for x in C():
...     print x
...
Traceback (most recent call last):
   File "<interactive input>", line 1, in ?
TypeError: iter() returned non-iterator of type 'int'

I'm not trying to catch the case where someone is deliberately violating 
the protocol.  Only the case where they've provided an object that 
doesn't conform to the protcol.


Clearly, complex objects don't conform to the protocol I want -- they 
don't support comparisons to ints.  This is easy to check:

try:
     x <= 1
except TypeError:
     raise TypeError('%s does not support comparisons to ints' %
                     type(x).__name__)

Now str objects also don't conform my protocol -- they aren't comparable 
to integers in any meaningful sense.  Ideally, I should be able to use 
the same code as above for str objects (and get a TypeError like "str 
objects cannot be compared with int objects"), but unfortunately, the 
Python wart of cross-type default comparisons gets in the way.  I look 
forward to the day when Python 3.0 removes such comparisons.  =)

Steve



More information about the Python-list mailing list