check if object is number

M

Michael Hartl

As I mention below, I mistook the function from my utilities file for a
Python built-in; here's the implementation:

#def isnumber(x):
# "Is x a number? We say it is if it has an __int__ method."
# return hasattr(x, '__int__')
 
P

Peter Hansen

marco said:
Maybe this can help?

def isnumber(x):
try:
return(x == x-0)
except:
return False

Not exactly foolproof:
.... try: return (x == x-0)
.... except: return False
....
>>> import numarray
>>> a = numarray.arange(1.1, 5.5)
>>> a array([ 1.1, 2.1, 3.1, 4.1, 5.1])
>>> print '%s:\t' % a, isnumber(a)
[ 1.1 2.1 3.1 4.1 5.1]: [1 1 1 1 1]

The result is actually this:
array([1, 1, 1, 1, 1], type=Bool)

And if you try to call bool() on it (as perhaps
your isnumber() routine already should have, rather
than relying on == to return a boolean):
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "C:\a\python24\Lib\site-packages\numarray\generic.py", line 477, in
__nonzero__
raise RuntimeError("An array doesn't make sense as a truth value. Use
sometrue(a) or alltrue(a).")
RuntimeError: An array doesn't make sense as a truth value. Use sometrue(a) or
alltrue(a).

Yuck.

Of course, most of the other definitions of "is a number" that
have been posted may likewise fail (defined as not doing what the
OP would have wanted, in this case) with a numarray arange.
Or maybe not. (Pretty much all of them will call an arange a
number... would the OP's function work properly with that?)

-Peter
 
S

Steven Bethard

Peter said:
Of course, most of the other definitions of "is a number" that
have been posted may likewise fail (defined as not doing what the
OP would have wanted, in this case) with a numarray arange.
Or maybe not. (Pretty much all of them will call an arange a
number... would the OP's function work properly with that?)

No, but it will fail properly since my code basically looks like:

def f(max=None):
...
while max is None or n <= max:
...
# complicated incrementing of n

So if max is an array, though all of the proposed isnumber checks will
call it a number, my code will (rightly) fail when the array (n <= max)
gets __nonzero__ called in the while condition. I guess I'd prefer it
to fail in the isnumber check, but overall, I'm more concerned that
_some_ error is produced, not necessarily which one. (I'm also not
thrilled that bool(array) raises a RuntimeError instead of a TypeError...)

Steve
 
M

Michael Spencer

Steven said:
No, but it will fail properly since my code basically looks like:

def f(max=None):
...
while max is None or n <= max:
...
# complicated incrementing of n

So if max is an array, though all of the proposed isnumber checks will
call it a number, my code will (rightly) fail when the array (n <= max)
gets __nonzero__ called in the while condition. I guess I'd prefer it
to fail in the isnumber check, but overall, I'm more concerned that
_some_ error is produced, not necessarily which one. (I'm also not
thrilled that bool(array) raises a RuntimeError instead of a TypeError...)

Steve
Steve,

How about explicitly calling an adapter in your function, e.g.?
> def f(max=None):
> max = number(max)
> while max is None or n <= max:
> ...
> # complicated incrementing of n

then you can define number to document the required behavior and return more
useful exceptions if the object fails. At the same time, anyone who wants to
use a custom number class with your function has a ready-made unittest.
... """Adapts obj to be numeric, or fails helpfully"""
... if isinstance(obj, (int, float, long, )): # these types conform
... return obj
... elif isinstance(obj, basestring): # these types have a known adaptation
... return int(obj)
... else: # check the object exhibits the required behavior
... try:
... assert obj+1 >= 1
... except Exception, err:
... raise TypeError, "obj does not support addition and comparisons
with numbers (%s)" % err
... return obj
... ... def __init__(self, data):
... self.data = data
... def __add__(self, other):
... return MyNumber(self.data + other)
... def __cmp__(self, other):
... return self.data.__cmp__(other)
...Traceback (most recent call last):
File "<input>", line 1, in ?
File "<input>", line 11, in number
TypeError: obj does not support addition and comparisons with numbers (cannot
>>> number(array.array("i",[1]))
Traceback (most recent call last):
File "<input>", line 1, in ?
File "<input>", line 11, in number
TypeError: obj does not support addition and comparisons with numbers (can only
append array (not "int") to array)
Cheers
Michael
 
S

Steven Bethard

Michael said:
How about explicitly calling an adapter in your function, e.g.?

Yup, that's basically what I'm doing right now. The question was really
how to define that adapter function. =)

Steve
 
M

Michael Spencer

Steven said:
Yup, that's basically what I'm doing right now. The question was really
how to define that adapter function. =)

Steve
OK - then my entry is:
assert obj+1 >= 1
:)

Michael
 
F

Francis Girard

Le vendredi 11 Février 2005 20:11, Steven Bethard a écrit :
Is there a good way to determine if an object is a numeric type?
Generally, I avoid type-checks in favor of try/except blocks, but I'm
not sure what to do in this case:

def f(i):
...
if x < i:
...

The problem is, no error will be thrown if 'i' is, say, a string:

py> 1 < 'a'
True
py> 10000000000 < 'a'
True

But for my code, passing a string is bad, so I'd like to provide an
appropriate error.


This is a very bad Python feature that might very well be fixed in version 3.0
according to your own reply to a previous thread. This problem clearly shows
that this Python feature does hurt.

Here's a transcript of the answer :
Yes, that rule being to compare objects of different types by their type
names (falling back to the address of the type object if the type names
are the same, I believe).  Of course, this is arbitrary, and Python does
not guarantee you this ordering -- it would not raise backwards
compatibility concerns to, say, change the ordering in Python 2.5.


I believe at the time, people thought that comparison should be defined
for all Python objects.  Guido has since said that he wishes the
decision hadn't been made this way, and has suggested that in Python
3.0, objects of unequal types will not have a default comparison.

Probably this means ripping the end off of default_3way_compare and
raising an exception.  As Fredrik Lundh pointed out, they could, if they
wanted to, also rip out the code that special-cases None too.

Steve



Regards

Francis Girard
 
A

Antoon Pardon

Op 2005-02-11 said:
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.

Actually no, floats don't meet this behaviour or more specifically
floats don't guarantee this behaviour. It depends of course on
your implementation of f, but it is possible with floats to keep
incrementing and never reach a maximum.
 
S

Steven Bethard

Antoon said:
Actually no, floats don't meet this behaviour or more specifically
floats don't guarantee this behaviour. It depends of course on
your implementation of f, but it is possible with floats to keep
incrementing and never reach a maximum.

My code won't hit this corner case. I'm incrementing with integers.

Steve
 
S

Steven Bethard

Fredrik said:
incrementing what with integers?

True

I mean that the number that's being incremented is an integer:

py> f = 9007199254740992.0
py> i = 9007199254740991
py> i <= f
True
py> i += 1
py> i <= f
True
py> i += 1
py> i <= f
False

Steve
 
S

Steven Bethard

Michael said:
At least not a legal one for Steven's function as I understood it

No, -1 is still a "number" for my particular case.

Basically, I want "numbers" to be valid upper bounds to an increasing
sequence of integers. This means that "numbers" must be comparable to
integers and must behave properly as upper bounds to integers. More
formally:

If n is a "number" (in my particular sense), then there exists an
integer i such that i > n, and for all integers i such that i > n and
for all positive integers x, i + x > n.

STeVe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,219
Messages
2,571,120
Members
47,741
Latest member
WilliamsFo

Latest Threads

Top