I searched the string and cMath libraries for a similar function
without success. I can think of at least 3 or 4 ways to build my
own function.
Here's what I came up with as a proof-of-concept. Are there
'better' ways to perform this type of test?
Thanks,
Malcolm
<code>
def isnumber( input ):
try:
if '.' in input:
num = float( input )
else:
num = int( input )
return True
except ValueError:
return False
if __name__ == '__main__':
tests = """
12
-12
-12.34
.0
.
1 2 3
1 . 2
just text
"""
for test in tests.split( '\n' ):
print 'test (%0s), isnumber: %1s' % \
( test.strip(), isnumber( test ) )
</code>
You code doesn't check for several float representations like "1e10",
"1E10", "inf" and "nan".
Christian
> What's the Pythonic way to determine if a string is a number? By
> number I mean a valid integer or float.
try:
int(number)
is_an_int = True
except:
is_an_int = False
try:
float(number)
is_a_float = True
except:
is_a_float = False
is_a_number = (is_an_int or is_a_float)
> What's the Pythonic way to determine if a string is a number? By
> number I mean a valid integer or float.
try:
int(myString)
except ValueError:
print "That's bogus, man"
Please don't teach new Python developers to use bare excepts. In fact
never use bare excepts at all!
Christian
float(myString)
This will work even if it's an int.
I agree that the bare except is incorrect in this situation, but I don't
agree that you should *never* use them.
They make sense when you need to recover from any error that may occur,
possibly as the last resort after catching and dealing with more specific
exceptions. In an unattended embedded system (think Mars Rover), the
top-level code might well be:
while 1:
try:
main()
except:
reset()
or perhaps even (Range Safety Controller):
try:
main()
except:
self_destruct()
Christian: Thanks for reminding me about exponential formats. My updated
code accounts for these type of numbers. I don't need to handle inf or
nan values. My original code's except catches an explicit ValueError
exception per your concern about bare excepts.
Malcolm
<code>
# str_to_num.py
def isnumber( input ):
try:
num = float( input )
return True
except ValueError:
return False
if __name__ == '__main__':
tests = """
12
-12
-12.34
.0
.
1 2 3
1 . 2
1e10
1E10
inf
nan
12 and text
A bare except should be used when followed by a raise
try:
func()
except:
log_error()
raise
> They make sense when you need to recover from any error that may occur,
> possibly as the last resort after catching and dealing with more specific
> exceptions. In an unattended embedded system (think Mars Rover), the
> top-level code might well be:
>
> while 1:
> try:
> main()
> except:
> reset()
Do you really want to except SystemExit, KeyboardInterrupt, MemoryError
and SyntaxError?
Christian
Just for the info, Malcolm, you don't actually
need to assign the result of float (input)
to anything if you don't need to use it. All
you're looking for is the exception. Let the
intepreter convert it and then throw it away.
Also, as an alternative style which can be more
appropriate depending on the structure and intention
of what you're doing, you can use the else: clause
of the try-except block.
try:
float (input)
except ValueError:
return False
else:
return True
TJG
> Just for the info, Malcolm, you don't actually need to assign the result of float (input) to anything if you don't need to use it. All you're looking for is the exception. Let the intepreter convert it and then throw it away.
Yes!
> Also, as an alternative style which can be more appropriate depending on the structure and intention of what you're doing, you can use the else: clause of the try-except block.
>
> try:
> float (input)
> except ValueError:
> return False
> else:
> return True
I follow the semantics, but I don't know why I would prefer the try/else
technique over the simpler:
try:
float( input )
return True
except ValueError:
return False
Thank you for your feedback,
Malcolm
>> They make sense when you need to recover from any error that may occur,
>> possibly as the last resort after catching and dealing with more specific
>> exceptions. In an unattended embedded system (think Mars Rover), the
>> top-level code might well be:
>>
>> while 1:
>> try:
>> main()
>> except:
>> reset()
>
> Do you really want to except SystemExit, KeyboardInterrupt, MemoryError
> and SyntaxError?
Exactly. A normal program should never do anything more comprehensive than
try:
some_function ()
except StandardError:
some_handling ()
IMHO
Mel.
Pretty good, but what about 0x23?
def isnumber( input ):
try:
num = float(input)
return True
except ValueError:
try:
num = int(input, 0) # Convert to int, base spec in arg
return True
except ValueError:
return False
--Scott David Daniels
Scott....@Acm.Org
> Philip Semanchuk schrieb:
>>
>> On Feb 15, 2009, at 12:46 PM, pyt...@bdurham.com wrote:
>>
>>> What's the Pythonic way to determine if a string is a number? By
>>> number I mean a valid integer or float.
>>
>>
>> try:
>> int(number)
>> is_an_int = True
>> except:
>> is_an_int = False
>
> Please don't teach new Python developers to use bare excepts.
Good point; my example is lazy.
I should know better as I myself got burned on bare excepts a few
times when I started with Python.
Do you care about numbers that are representable as an int, but are
treated as inf by float()?
For example:
| >>> s = '1' * 310
| >>> float(s)
| inf
| >>> a = int(s)
| >>> # OK
> Christian Heimes wrote:
> > Roy Smith wrote:
>
> >> They make sense when you need to recover from any error that may occur,
> >> possibly as the last resort after catching and dealing with more specific
> >> exceptions. In an unattended embedded system (think Mars Rover), the
> >> top-level code might well be:
> >>
> >> while 1:
> >> try:
> >> main()
> >> except:
> >> reset()
> >
> > Do you really want to except SystemExit, KeyboardInterrupt, MemoryError
> > and SyntaxError?
Absolutely. Let's take my example -- you're writing software for a Mars
Rover. I have no idea how you might get a MemoryError, but let's say you
do. Which would you rather do, perform a system reset, or print a stack
trace and wait for a friendly Martian to come along and reboot you?
You may think I'm being silly, but I'm dead serious. The many layers of
"It's impossible for this to happen, but if it does let's do something to
try and recover" processing saved that mission several times over. In some
applications, there's no such thing as "halt".
> Pretty good, but what about 0x23?
>
<snipped>
> num = int(input, 0) # Convert to int, base spec in arg
>
Very nice! I wasn't familiar with the use of 0 as a radix value. A quick
visit back to the documentation and I'm an enlightened man :)
Thanks for your feedback,
Malcolm
> Do you care about numbers that are representable as an int, but are treated as inf by float()?
>
> For example:
> | >>> s = '1' * 310
> | >>> float(s)
> | inf
> | >>> a = int(s)
> | >>> # OK
My code range checks all numbers once they've been parsed, so I don't
believe this will be a problem for me.
However, I appreciate you pointing out this behavior because I was
unaware of this subtle nuance. I'll make sure to add this to our code
review checklist.
teststring = '15719'
teststring.isdigit()
returns True
That takes care of integers.
from string import digits
digits
'0123456789'
now you have all the digits and you can do set testing in your logic
to see if the teststring has anything in digits
A dumb way to test is alphanumeric
teststring2 = '105.22'
teststring2.isalnum()
returns True
now you can go on from there and test to further to eliminate
'abcd385laf8' which on alnum() also returns true.
Have fun,
Cheers,
PN
2009/2/16 <pyt...@bdurham.com>:
> What's the Pythonic way to determine if a string is a number? By
> number I mean a valid integer or float.
>
> I searched the string and cMath libraries for a similar function
> without success. I can think of at least 3 or 4 ways to build my
> own function.
>
> Here's what I came up with as a proof-of-concept. Are there
> 'better' ways to perform this type of test?
>
> Thanks,
> Malcolm
>
> <code>
> def isnumber( input ):
> try:
> if '.' in input:
> num = float( input )
> else:
> num = int( input )
> return True
>
> except ValueError:
> return False
>
> if __name__ == '__main__':
> tests = """
> 12
> -12
> -12.34
> .0
> .
> 1 2 3
> 1 . 2
> just text
> """
>
> for test in tests.split( '\n' ):
> print 'test (%0s), isnumber: %1s' % \
> ( test.strip(), isnumber( test ) )
>
> </code>
build a set from digits + '.' and use that for testing.
Cheers,
PN
2009/2/16 Python Nutter <python...@gmail.com>:
Actually its instantiating not type casting and it works
by using the type's actual description of the data it
accepts. This looks pretty good approach instead of trying
to copy (incomplete as it has been shown not only digits and
. constitute a float) already implemented code.
Of course if you want to limit the range of accepted data
even more, then isdigit and friends can be used -
maybe you could time both approaches with a set of data.
Regards
Tino
Yeah, having your mars rower forever running in a loop to try to convert
some random string to a number is sure something you want to achieve.
Tino
That is a fine solution.
Last time I had to solve this I had a specific format of number to
parse - I didn't want to include all the python formats. This is what
I came up with... This particular code returns the converted number
or 0.0 - adjust as you see fit!
import re
_float_pattern = re.compile(r"^\s*([-+]?(\d*\.)?\d+([eE][-+]?\d+)?)")
def atof(value):
"""
Convert a string to an float in the same way the c-library atof()
does. Ie only converting as much as it can and returning 0.0 for
an error.
"""
match = _float_pattern.search(value)
if match:
return float(match.group(1))
return 0.0
>>> atof("15.5 Sausages")
15.5
>>> atof(" 17.2")
17.199999999999999
>>> atof("0x12")
0.0
>>> atof("8.3.2")
8.3000000000000007
>>> atof("potato")
0.0
>>>
--
Nick Craig-Wood <ni...@craig-wood.com> -- http://www.craig-wood.com/nick
Their is a good answer given on Rosetta Code here:
http://www.rosettacode.org/wiki/IsNumeric#Python
- Paddy.
>> > Do you really want to except SystemExit, KeyboardInterrupt, MemoryError
>> > and SyntaxError?
>
> Absolutely. Let's take my example -- you're writing software for a Mars
> Rover. I have no idea how you might get a MemoryError, but let's say you
> do. Which would you rather do, perform a system reset, or print a stack
> trace and wait for a friendly Martian to come along and reboot you?
>
> You may think I'm being silly, but I'm dead serious. The many layers of
> "It's impossible for this to happen, but if it does let's do something to
> try and recover" processing saved that mission several times over. In
> some applications, there's no such thing as "halt".
Okay, but that surely falls under chapter 18 of the "Advanced Python
Programming for the Mars Rover" book rather than chapter 5 of "Newbies
Guide to Python".
In general, the right thing to do for unexpected exemptions is to let them
halt the program so you can find out about them and fix the bug, not to
hide the exception. There may be exceptions (pun intended) to this general
principle, but they're fairly unusual.
--
Steven
> Okay, but that surely falls under chapter 18 of the "Advanced Python
> Programming for the Mars Rover" book rather than chapter 5 of "Newbies
> Guide to Python".
Well, sure, but this thread started out with my taking, ahem, exception to
the statement, "never use bare excepts at all". I agree that doing so is
not typical, and not the kind of habit that new programmers should form
because it's not the kind of situation new programmers are likely to be
involved in. But, "never" was too strong a word.
Hmm, most places advocate or even outright recommend derriving your
own exceptions from Exception and not from StandardError. So maybe
your catch-all should be Exception? In that case you would be
catching warnings though, no idea what influence that has on the
warning system.
Regards
Floris
PS: Does anybody know why StopIterantion derrives from Exception while
GeneratorExit derrives from BaseException? This could be as annoying/
confusing as Warning.
`.' is locale dependent. Some locales might use `,' instead and maybe
there's even more out there that I don't know of. So developing this
yourself from scratch seems dangerous, let it bubble down to libc
which should handle it correctly.
Regards
Floris
Hmmm, this doesn't seem right to me.
Unless I'm missing something, won't your code think that "123.123.123"
is numeric? What about scientific or engineering notation with
exponents?
What's wrong with using python's own casting rules (given that you are
trying to emulate the way python behaves? Or, alternatively, using a
regular expression (as Nick Craig-Wood did).
Given these solutions, type-conversion and catching the ValueError
appears, to me, to be correct, the most concise, and the most readable
solution.
Of course, if you want to use your own set of rules for number
encoding, then building your own regular expression would seem to be
the right way to go.
Paddy
--
"Ray, when someone asks you if you're a god, you say YES!"
My point is that the coaching offered by this forum does not always fall
on deaf ears.
Thanks for everyone's help on this and all the other posts in this
forum.
Regards,
Malcolm