isNumber? check

Peter Otten __peter__ at web.de
Tue Sep 30 14:26:19 CEST 2003


Tony Meyer wrote:

> I would think that:
> """
> s = "123"
> value = isNumber(s)
> if value is None:
>     # do something that shows it's not a number.
>     # (obviously not raise a ValueError, because
>     # then there's no point using the function at
>     # all)
> # continue program, with value in value, if needed.
> """
> Would be a more logical way to do it.

I would still prefer

try:
   value = toNumber(s)
except ValueError:
    # handle error

> It's not.  It was an example case showing that there isn't any need to
> bother with regexs and the like if you don't want to - Python will do the
> work for you.  Assuming you trust the Python developers, you can trust
> that it will correctly check that the value is convertible into a number,
> and don't need to worry that you missed something in the regex (or
> whatever).

I wouldn't use regexes here, too.

> A real function would have a docstring...this is only c.l.p...

Everything that can be conveyed by the function name makes the code more
readable. Consider

def killTheBeast(beast):
    """ Does not actually kill the beast, but shows a grim face
        while hugging it
    """

(Sorry, couldn't resist)

> The OP asked for a function called isNumber.  I posted an example of one.

If a suggested improvement changes the functionality, you could explain the
name change to the OP.

> The program snippet doesn't throw an exception at the end; your example
> usage did.  If the code was going to raise a ValueError if it couldn't be
> converted, then it would be written differently; the OP didn't say that
> that
> was the case.  The program flow is really:
>  - convert to number and return
>  - if an exception was raised then return None, signifying that no number
> can be created
> 
> Lots of the stuff written about Python talks about using exceptions for
> code
> control, as this does.  This isn't C++.

No, this isn't C, and one advantage, I think, is that you no longer need to
check for special error values. (OK, I'm simplifying...)

>> I can think of very few situations where None could actually
>> be *used* instead of a numerical value.
> 
> Why would you want to *use* None?  It's simply the function signifying
> that it couldn't convert the number.
> 
>> > Note that "0" will come back as 0.0, though, because it
>> > evaluates as False. It would be easy enough to special case that, if
> necessary.
>> 
>> This is a bug that demonstrates that your isInt()/isFloat()
>> implementation is not even well suited to implement isNumber().
> 
> Rubbish.  This is me not taking care of every little detail in example
> code,
> for the sake of brevity, but warning that that is the case.  In any case,
> it still correctly determines if the object can be converted to a number,
> and
> still correctly returns the number it is converted to.  The only thing
> that
> is possibly incorrect is that it's a float instead of an int.  As I said,
> easily fixed.

It is easily fixed in this trivial example. However, when you use a special
value to signal an error in a sufficiently complex calling hierarchy, you
end up testing for it too often for my taste.

> You seem to have missed the whole point of the code snippet.  The idea is
> that you can use the conversion built into Python to check if a number can
> be converted, without having to write code that checks yourself.  Perhaps

Maybe I stressed the points I did *not* like too much. Again, I agree with
your no regexes policy. (Localization is a different story)

> you would like this more?
> 
> """
> def isNumber(s):
>     for f in [int, float,]:
>         try:
>             return f(s)
>         except ValueError:
>             pass
>     raise ValueError("Cannot convert to a number")
> """

You're right, I like that. Now give it a decent name (e.g. strToNumber())
and we have finally reached consensus :-)

> To me this doesn't seem as clear in explaining the concept, although it's
> more like code I would actually use.  This does return "0" as 0, and
> raises
> a ValueError is no conversion is possible.  The point is that the concept,
> which is what I was trying to convey, is the same.  If you really don't
> want the value returned, then you could just use:
> 
> """
> def isNumber(s):
>     for f in [int, float,]:
>         try:
>             f(s)
>         except ValueError:
>             continue
>         return True
>     return False
> """

I think I would build on previous work here:

def isNumber(s):
    try:
        strToNumber(s)
    except ValueError:
        return False
    return True

Peter




More information about the Python-list mailing list