I've been working in statically typed languages for awhile, and I've had to write some Python utilities recently. As part of those tools, I needed a semi-sane way to implement type checking to make it easier to understand the target type I'm working with.
def type_of(val: Any, target_type: Any) -> bool: """ Safely check to see if a value is typeOf(type). :param val: Value or variable to check. :param target_type: Type you want to check. It's important to know booleans are a subclass of integers, so t(False, (int,bool)) -> True :return: """ try: if isinstance(val, bool) and cast_to(val, bool): return True if isinstance(val, target_type): return True else: return False except ValueError: return False def cast_to(val: Any, target_type: [int, bool, str, list]) -> (bool, [int, bool, str, list]): """ If a value can be cast as that type, it will be. :param val: Value to be cast. :param target_type: Destination type. :return bool, [int, bool, str, list]: Returns True if it can be base with the proper type; False if not, with the value type. """ try: # if it's an int and greater than 1 or less than zero, it can't be a bool if (isinstance(val, int) and ((val > 1) or (val < 0))) and target_type is bool: return False, val nval = target_type(val) if isinstance(nval, target_type): return True, nval else: return False, val except ValueError: return False, val
It generally works as intended until I get to booleans, which I recently learned are a subclass of integers, and I've had problems consistently determining if something is a boolean. How can I improve my type check to properly handle booleans?