Proper way to assert type of variable in Python

PythonTestingAssert

Python Problem Overview


In using a function, I wish to ensure that the type of the variables are as expected. How to do it right?

Here is an example fake function trying to do just this before going on with its role:

def my_print(begin, text, end):
    """Print 'text' in UPPER between 'begin' and 'end' in lower
        
    """
    for i in (begin, text, end):
        assert isinstance(i, str), "Input variables should be strings"
    out = begin.lower() + text.upper() + end.lower()
    print out

def test():
    """Put your test cases here!
    
    """
    assert my_print("asdf", "fssfpoie", "fsodf")
    assert not my_print("fasdf", 33, "adfas")
    print "All tests passed"

test()

Is assert the right approach? Should I use try/except instead?

Also, my assert set of tests does not seem to work properly :S

Thanks pythoneers

Python Solutions


Solution 1 - Python

The isinstance built-in is the preferred way if you really must, but even better is to remember Python's motto: "it's easier to ask forgiveness than permission"!-) (It was actually Grace Murray Hopper's favorite motto;-). I.e.:

def my_print(text, begin, end):
    "Print 'text' in UPPER between 'begin' and 'end' in lower"
    try:
      print begin.lower() + text.upper() + end.lower()
    except (AttributeError, TypeError):
      raise AssertionError('Input variables should be strings')

This, BTW, lets the function work just fine on Unicode strings -- without any extra effort!-)

Solution 2 - Python

You might want to try this example for version 2.6 of Python.

def my_print(text, begin, end):
    "Print text in UPPER between 'begin' and 'end' in lower."
    for obj in (text, begin, end):
        assert isinstance(obj, str), 'Argument of wrong type!'
    print begin.lower() + text.upper() + end.lower()

However, have you considered letting the function fail naturally instead?

Solution 3 - Python

Doing type('') is effectively equivalent to str and types.StringType

so type('') == str == types.StringType will evaluate to "True"

Note that Unicode strings which only contain ASCII will fail if checking types in this way, so you may want to do something like assert type(s) in (str, unicode) or assert isinstance(obj, basestring), the latter of which was suggested in the comments by 007Brendan and is probably preferred.

isinstance() is useful if you want to ask whether an object is an instance of a class, e.g:

class MyClass: pass

print isinstance(MyClass(), MyClass) # -> True
print isinstance(MyClass, MyClass()) # -> TypeError exception

But for basic types, e.g. str, unicode, int, float, long etc asking type(var) == TYPE will work OK.

Solution 4 - Python

isinstance(x, str) is best if you can use it, but it does not work with generics. For example you cannot do:

isinstance(x, dict[str, int])

It will give a runtime error:

TypeError: isinstance() argument 2 cannot be a parameterized generic

If you are only interested in asserting a type for a static type checker you can use cast:

from typing import cast

x_as_dict = cast(dict[str, int], x)

Unlike isinstance() it doesn't actually do the type check so you have to check all of the keys and values yourself if necessary.

(I realise this isn't exactly what you asked for but "type assertion" is also used to refer to things like cast() so I'm avoiding another question that will get closed as duplicate.)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMorlockView Question on Stackoverflow
Solution 1 - PythonAlex MartelliView Answer on Stackoverflow
Solution 2 - PythonNoctis SkytowerView Answer on Stackoverflow
Solution 3 - PythoncryoView Answer on Stackoverflow
Solution 4 - PythonTimmmmView Answer on Stackoverflow