Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I type-check variables in Python?

I have a Python function that takes a numeric argument that must be an integer in order for it behave correctly. What is the preferred way of verifying this in Python?

My first reaction is to do something like this:

def isInteger(n):
    return int(n) == n

But I can't help thinking that this is 1) expensive 2) ugly and 3) subject to the tender mercies of machine epsilon.

Does Python provide any native means of type checking variables? Or is this considered to be a violation of the language's dynamically typed design?

EDIT: since a number of people have asked - the application in question works with IPv4 prefixes, sourcing data from flat text files. If any input is parsed into a float, that record should be viewed as malformed and ignored.

like image 545
Murali Suriar Avatar asked Jan 20 '09 23:01

Murali Suriar


People also ask

How check variable type in if condition Python?

Method #1 : Using isinstance(x, str) This method can be used to test whether any variable is a particular datatype. By giving the second argument as “str”, we can check if the variable we pass is a string or not.

How do you check if a variable is a type?

You can use the typeof operator to check the variable. It returns a string which indicates the type of the unevaluated operand.

How do I check data in Python?

In general, we use the type() function to check the data type of any variable used in Python. The type() function can return the data type with a single argument. However, the data types used in Python are a bit different from those used in C or C++.

What is type check in Python?

Type checking or hinting is a newer feature of Python that was added in Python 3.5. Type hinting is also known as type annotation. Type hinting is adding special syntax to functions and variable declarations that tell the developer what type the argument or variable is.


2 Answers

isinstance(n, int)

If you need to know whether it's definitely an actual int and not a subclass of int (generally you shouldn't need to do this):

type(n) is int

this:

return int(n) == n

isn't such a good idea, as cross-type comparisons can be true - notably int(3.0)==3.0

like image 63
bobince Avatar answered Oct 27 '22 17:10

bobince


Yeah, as Evan said, don't type check. Just try to use the value:

def myintfunction(value):
   """ Please pass an integer """
   return 2 + value

That doesn't have a typecheck. It is much better! Let's see what happens when I try it:

>>> myintfunction(5)
7

That works, because it is an integer. Hm. Lets try some text.

>>> myintfunction('text')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in myintfunction
TypeError: unsupported operand type(s) for +: 'int' and 'str'

It shows an error, TypeError, which is what it should do anyway. If caller wants to catch that, it is possible.

What would you do if you did a typecheck? Show an error right? So you don't have to typecheck because the error is already showing up automatically.

Plus since you didn't typecheck, you have your function working with other types:

Floats:

>>> print myintfunction(2.2)
4.2

Complex numbers:

>>> print myintfunction(5j)
(2+5j)

Decimals:

>>> import decimal
>>> myintfunction(decimal.Decimal('15'))
Decimal("17")

Even completely arbitrary objects that can add numbers!

>>> class MyAdderClass(object):
...     def __radd__(self, value):
...             print 'got some value: ', value
...             return 25
... 
>>> m = MyAdderClass()
>>> print myintfunction(m)
got some value:  2
25

So you clearly get nothing by typechecking. And lose a lot.


UPDATE:

Since you've edited the question, it is now clear that your application calls some upstream routine that makes sense only with ints.

That being the case, I still think you should pass the parameter as received to the upstream function. The upstream function will deal with it correctly e.g. raising an error if it needs to. I highly doubt that your function that deals with IPs will behave strangely if you pass it a float. If you can give us the name of the library we can check that for you.

But... If the upstream function will behave incorrectly and kill some kids if you pass it a float (I still highly doubt it), then just just call int() on it:

def myintfunction(value):
   """ Please pass an integer """
   return upstreamfunction(int(value))

You're still not typechecking, so you get most benefits of not typechecking.


If even after all that, you really want to type check, despite it reducing your application's readability and performance for absolutely no benefit, use an assert to do it.

assert isinstance(...)
assert type() is xxxx

That way we can turn off asserts and remove this <sarcasm>feature</sarcasm> from the program by calling it as

python -OO program.py
like image 13
nosklo Avatar answered Oct 27 '22 15:10

nosklo