Python Forum

Full Version: how to determine if an object is a number
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
what is the best way to determine if an object passed in to a function is a number? i am thinking that i should just do arithmetic in try/except and set False to another variable that is initially True. but, is there something better?
def number_text(var):
    if isinstance(var, (int, float)):
        print('Is a number')
    else:
        print('Not a number')

number_text(1)
number_text(1.2)
number_text('1')
@Windspar, that doesn't work for Decimal, imaginary, long, or other kinds of numbers.

@Skaperen, what exactly do you mean by "determine if an object passed in to a function is a number"? It sounds like you already have a Python object, so you're not dealing with a user-input string.

Python is not only dynamically typed (by design) but also duck typed (by convention), so yes as you say the "Pythonic" thing to do would be to try to use it and then catch an exception if you're really concerned about an operation not being supported, but in practice we usually don't bother looking for an exception. Usually we wouldn't have an is_number function like you're describing, even.
If you know the type. You should be able to detect it.
from decimal import Decimal
from fractions import Fraction

NUMBER = (int, float, complex, Decimal, Fraction)

def is_number(n):
    if isinstance(n, NUMBER):
        print(n, 'is a number')
    else:
        print(n, 'is not a number')

is_number(1)
is_number(1.2)
is_number(Decimal(2.02))
is_number(Fraction(2,3))
is_number(1j)
is_number('1')
(Jul-09-2018, 11:00 PM)Windspar Wrote: [ -> ]If you know the type. You should be able to detect it.
If all the OP wants is to type-check, that may be fine. It depends on the definition of "number". If that definition is the set of types you describe, that works.

I think a big part of why Python tends to use duck typing by convention is this - a more flexible definition of "number" isn't its OOP is-a relationship with a set of classes (or types), rather, it's a set of operations available on an object. Defining the types in advance precludes new user types that support all the operations, unless they inherit from something. Even that aside, sometimes a third-party library comes along which you might want compatibility with, so the user doesn't even have the option of extending that class. It is for this reason that I strongly recommend against type-checking, unless it's really the only option.

On a potentially ironic note... if you're serious about the actual types (especially if we're talking about objects), I recommend you check out type hinting. It can help catch these issues before you run your script, instead of during. Why might this be ironic? Python's type hinting doesn't support duck typing (Scala, as a comparison, offers "structural typing" which is basically static duck-typing; it is not widely used and has performance issues but it's a proof-of-concept). I look forward to the day when Python does support type hints for duck typing, but it's not today :)
(Jul-09-2018, 10:18 PM)micseydel Wrote: [ -> ]@Skaperen, what exactly do you mean by "determine if an object passed in to a function is a number"? It sounds like you already have a Python object, so you're not dealing with a user-input string.

Python is not only dynamically typed (by design) but also duck typed (by convention), so yes as you say the "Pythonic" thing to do would be to try to use it and then catch an exception if you're really concerned about an operation not being supported, but in practice we usually don't bother looking for an exception. Usually we wouldn't have an is_number function like you're describing, even.
it might actually be a user input string. so i am putting conversions under the try clause, too. i'm not really concerned what is under try may well just be the start of how the number will be used. i just want to include enough meaning in the message (in the raised exception) to help the end user in lieu of the programmer since some errors may well just be a user error.

of course the programmer should understand the traceback and correct errors ... if it is an error in the code. but the end user who knows nothing about coding, can make mistakes, too, such as typing a comma instead of a period in a number (perhaps because they are in Europe and it's a habit). whatever it is, if i am the programmer, i want to tell users about their errors .. or where i am making tools for programmers, make it easy for them to inform their users.

what if you have a program for farmers to type in how many acres they need seed for and this one farmer types in: 1,649.5

do you want to say to him ... ValueError: could not convert string to float: '1,649.5'

or maybe ... decimal.InvalidOperation: [<class 'decimal.ConversionSyntax'>]

i wouldn't. at they very least i'd want to say ... the number of acres is not a valid number. or i could do better and tell him not to type those commas. or maybe i could just take it that way.

when some web shop wants CC numbers without the spaces, i just want to tell them "how ****ing hard is it to delete spaces in the code" or maybe just "cc=cc.replace(' ','') # how hard is that?".

yeah, if "a number" to the code i'm writing could be a decimal string and/or a complex number, the the test needs to include that. but what if the next project would screw up bad with a complex number and some user types one in. it needs different code. gotta define what you want. do you want to allow the switched use of commas and periods? is "1,2" a number?
found a better way: numbers.Number