"""Example module without type checking. Pros: Clean, easily readable and extensible code that gets down to business fast. Pinpointed tracebacks with good error messages. Now we catch errors of the type a = MyClass() a.int_member = 'moo!" a.process_data(1) Cons: With many args and allowed types, the type definitions on the decorator lines will be hard to correlate to the args that they refer to (probably not impossible to workaround though...?). A decorator for each method everywhere? That can't be the purpose of python!? There has to be a better way?! Property bloat. +7 or more lines of boilerplate code for each added data member (can this be done neater?). If I at some point decide that floats are also ok, I only need to update the docs, decorators and properties... hmm... """ def method_argtypes(*typedefs): """Rudimentary typechecker decorator generator. If you're really interested in this stuff, go check out Michele Simionato's decorator module instead. It rocks. Google is your friend. IN: *typedefs: or > The allowed types for each arg to the method, self excluded. Will be used with isinstance(), so valid typedefs include int or (int, float). """ def argchecker(fcn): import inspect names = inspect.getargspec(fcn)[0][1:] def check_args(*args): for arg, value, allowed_types in zip(names, args[1:], typedefs): if not isinstance(value, allowed_types): one_of = '' if hasattr(allowed_types, '__len__'): one_of = "one of " msg = ".%s() argument %r must be %s%s" msg %= fcn.__name__, arg, one_of, allowed_types raise TypeError(msg) return fcn(*args) return check_args return argchecker class MyClass(object): """My example class.""" @method_argtypes(int) def __init__(self, int_member = 0): """Instantiate a new MyClass object. IN: int_member = 0: Set the value for the data member. Must be int. """ # Initiallization starts here. May for example contain assignment. self.int_member = int_member def _get_int_member(self): return self.__int_member def _set_int_member(self, value): if not isinstance(value, int): raise TypeError("int_member must be type int") self.__int_member = value int_member = property(_get_int_member, _set_int_member) del _get_int_member, _set_int_member @method_argtypes(int) def process_data(self, data): """Do some data processing. IN: data: New information that should be incorporated. Must be int. """ # Data processing starts here. May for example contain addition: self.int_member += data # Test code. Decomment to play. :-) #a = MyClass('moo') #a = MyClass(9) #a.int_member = 'moo' #a.process_data('moo') #a.process_data(9)