Who in Python has to check if the correct type of the arguments is passed to a function or method:

  1. The programmer calling the function must ensure that the type of the argument passed is correct. The function does not explicitly check the argument passed in the first stages, but simply uses it as if it were a reliably correct type. In the course of operation, functions can themselves be generated or explicitly generated various exceptions that will indicate the wrong argument. This exception will be described in docstring

  2. The function explicitly checks the type of the passed argument at the first stage and throws an exception if something is wrong, for example, TypeError.

  3. Something else

?

For example, if we pass to an function (for example) not an iterable, but an integer or a real number, then a TypeError exception is thrown (since int and float are not iterable). But at the very beginning, you can explicitly check yourself, for example, that the argument passed is an iterable object and generate something.

 def is_positive_or_zero_values ​​(iterable):
     "" "Check whether all elements in iterable have numbers equal to or greater than zero.

     Args:
         iterable: an iterable object containing values ​​to check.
     Returns:
         bool: True, if all elements in iterable have numbers that are equal to or greater than zero ..
               False, otherwise.
     "" "
     if iterable:
         if is_numbers (iterable):
             return all (map (lambda x: x> = 0, iterable))
         else:
             return false
     else:
         return false

    2 answers 2

    This theme has been raised in both Python in Nutshell and Fluent Python . Pythonic way - do not check arguments at all. Quote from Glossary:

    If you look at the type of object or attribute, it is not necessary. rather than specific types of well-designed code by polymorphic substitution. Duck-typing avoids tests using type () or isinstance (). Instead, it is typically employs the EAFP (Easier to Ask Forgiveness than Permission) style of programming.

      from functools import wraps import inspect def checker(fn): @wraps(fn) def wrapper(*args, **kwargs): insp = inspect.getfullargspec(fn) for name, _type in insp.annotations.items(): arg = args[insp.args.index(name)] msg = '%s=%s' % (name, arg), '%s - %s' % (_type, _type == type(arg)) print(msg) if not isinstance(arg, _type): raise UserWarning(msg) return fn(*args, **kwargs) return wrapper @checker def testFn(dt: dict, num: int, st: str): print('OK\n') testFn({'key': True}, 1, 'asd') testFn({'key': None}, 2, 77) 

      out:

       ('num=1', "<class 'int'> - True") ('st=asd', "<class 'str'> - True") ("dt={'key': True}", "<class 'dict'> - True") OK ('num=2', "<class 'int'> - True") ('st=77', "<class 'str'> - False") Traceback (most recent call last): File "C:/Scripts/python/2016/3/213123.py", line 22, in <module> testFn({'key': None}, 2, 77) File "C:/Scripts/python/2016/3/213123.py", line 13, in wrapper raise UserWarning(msg) UserWarning: ('st=77', "<class 'str'> - False") 
      • It does not answer the question "how to". - D-side
      • is there a correct way? it all depends on the task. Checking the arguments in the decorator fits point 3 - vadim vaduxa
      • 2
        The essence of the question: "when what way to choose." You have a "way", but not a "when." This I mean, it is worth commenting on what was written in the answer, explaining when it is appropriate. - D-side