Correct way to check against type given by string in Python

Question:

In short, if I have:

str_type = "int"
to_check = 1

what is the best way to implement the following check?

if isinstance(to_check, str_type):
...

More detailed:

I want to use type information given by one JSON file to check the values of another JSON file.

So if I have template.json:

{
  "param1": "int",
  "param2": "bool"
}

and with_values.json:

{
  "param1": 2,
  "param2": True
}

I then want to do a check like this:

if isinstance(with_values["param1"], template["param1"]):
...

This code fails because the second parameter of isinstance() must by a type object, rather than the string provided.

From my searching, I see some options, such as:

Converting the ‘type strings’ from template.json using a dictionary:

TYPES = {
  'int' : int,
  'str' : str,
...
}

if isinstance(with_values["param1"], TYPES[template["param1"]]):

or using eval (which is supposed to be discouraged but is safe enough in this case?):

if isinstance(with_values["param1"], eval(template["param1"])):

or I could just replace the ‘type strings’ with prototype values:

{
  "param1": 0,
  "param2": True
}

if isinstance(with_values["param1"], type(template["param1"]): # or type() is/== type()

There is also pydoc.locate, but it seems inappropriate to use a documentation module for this purpose. (Also, I can’t find a reference for this function, or really any extensive documentation for pydoc. Am I missing something?)

Or perhaps there is a better solution available.
So what is the most Pythonic (or just best in accordance with general principles) way of approaching this?
(Let’s assume only builtin types, but if the solution changes for self-defined types, then it would be good to include this for completeness.)

Asked By: ADuckTyping

||

Answers:

I think the best solution is to build a dictionary with string value corresponding to type. Then we can use build a simple function to check it

def check_types(value, expected_type: str):
    types = {
        "int": int,
        "str": str,
        "float": float
    }
    return isinstance(value, types[expected_type])

print(check_types(1, "int"))

If you want to specifically check for type and not subclasses(e.g. booleans are represented as integers). Using the following code will return whether the boolean is an integer False

def check_types(value, expected_type: str):
    types = {
        "bool": bool,
        "int": int,
        "str": str,
        "float": float
    }
    return type(value) == types[expected_type]
Answered By: Aleksander Ikleiw
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.