A Simple Method for checking the parameter types in Python.
Python is a weak type language, and many friends who transfer from C/C ++ are not very comfortable at first. For example, you cannot specify the parameter type when declaring a function. Using C for analogy, that is, all parameters are of the void * type! Forced conversion of the void type is widely regarded as a bad habit in C ++.
Python naturally has no type forced conversion because it is a dynamic language. First, all objects are inherited from objects. Second, they have powerful introspection. If a method that does not exist is called, an exception is thrown. In most cases, we do not need to perform parameter type check except for some special cases. For example, if a function accepts a str type, unicode is input in the result during the actual call, and no code is overwritten during the test, the problem is serious. The solution is also very simple. With the help of Python's introspection, it is easy to determine the parameter type. However, writing and checking code everywhere is cumbersome, and the actual value it brings is not high. A good solution is to use the decorator.
''' >>> NONE, MEDIUM, STRONG = 0, 1, 2 >>> >>> @accepts(int, int, int) ... def average(x, y, z): ... return (x + y + z) / 2 ... >>> average(5.5, 10, 15.0) TypeWarning: 'average' method accepts (int, int, int), but was given (float, int, float) 15.25'''def accepts(*types, **kw): """ Function decorator. Checks that inputs given to decorated function are of the expected type. Parameters: types -- The expected types of the inputs to the decorated function. Must specify type for each parameter. kw -- Optional specification of 'debug' level (this is the only valid keyword argument, no other should be given). debug = ( 0 | 1 | 2 ) """ if not kw: # default level: MEDIUM debug = 1 else: debug = kw['debug'] try: def decorator(f): def newf(*args): if debug == 0: return f(*args) assert len(args) == len(types) argtypes = tuple(map(type, args)) if argtypes != types: msg = info(f.__name__, types, argtypes, 0) if debug == 1: print >> sys.stderr, 'TypeWarning: ', msg elif debug == 2: raise TypeError, msg return f(*args) newf.__name__ = f.__name__ return newf return decorator except KeyError, key: raise KeyError, key + "is not a valid keyword argument" except TypeError, msg: raise TypeError, msgdef info(fname, expected, actual, flag): """ Convenience function returns nicely formatted error/warning msg. """ format = lambda types: ', '.join([str(t).split("'")[1] for t in types]) expected, actual = format(expected), format(actual) msg = "'%s' method " % fname \ + ("accepts", "returns")[flag] + " (%s), but " % expected\ + ("was given", "result is")[flag] + " (%s)" % actual return msg
In essence, this is also a runtime check, but the effect is already good.
For more interesting decorations, refer to this article http://wiki.python.org/moin/PythonDecoratorLibrary