How to use Python decorators to check function arguments?

python, python-decorators

Solution

From the Decorators for Functions and Methods:

Python 2

def accepts(*types):
    def check_accepts(f):
        assert len(types) == f.func_code.co_argcount
        def new_f(*args, **kwds):
            for (a, t) in zip(args, types):
                assert isinstance(a, t), \
                       "arg %r does not match %s" % (a,t)
            return f(*args, **kwds)
        new_f.func_name = f.func_name
        return new_f
    return check_accepts

Python 3

In Python 3 `func_code` has changed to `__code__` and `func_name` has changed to `__name__`.

def accepts(*types):
    def check_accepts(f):
        assert len(types) == f.__code__.co_argcount
        def new_f(*args, **kwds):
            for (a, t) in zip(args, types):
                assert isinstance(a, t), \
                       "arg %r does not match %s" % (a,t)
            return f(*args, **kwds)
        new_f.__name__ = f.__name__
        return new_f
    return check_accepts

Usage:

@accepts(int, (int,float))
def func(arg1, arg2):
    return arg1 * arg2

func(3, 2) # -> 6
func('3', 2) # -> AssertionError: arg '3' does not match <type 'int'>

`arg2` can be either `int` or `float`

Problem

I would like to define some generic decorators to check arguments before calling some functions. Something like: ``` @checkArguments(types = ['int', 'float']) def myFunction(thisVarIsAnInt, thisVarIsAFloat) ''' Here my code ''' pass ``` Side notes: - Type checking is just here to show an example - I'm using Python 2.7 but Python 3.0 whould be interesting too EDIT 2021: funny that type checking did not go antipythonic in the long run with type hinting and mypy.

Original source

Related problems