This fun little recipe uses Python 2.4 decorators to force function arguments to be of a specified type. If a type mismatch occurs, a TypeError is raised.
It fun, cheap, and dirty. And probably nasty.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import time
import types
class StrictlyType(object):
"""Returns a strictly typed function"""
def __init__(self,*args):
self.args = args
def __call__(self, f):
def func(*args):
for a in zip(self.args, [type(arg) for arg in args]):
if a[0] is not a[1]:
raise TypeError, 'Expected %s, got %s' % a
v = f(*args)
return v
func.func_name = f.func_name
return func
@StrictlyType(types.IntType, types.FloatType)
def z(a,b):
return a + b
print z(4,5.1)
#9.1
print z(4,5)
#Traceback (most recent call last):
# File "st.py", line 24, in ?
# print z(4,5)
# File "st.py", line 12, in func
# raise TypeError, 'Expected %s, got %s' % a
#TypeError: Expected <type 'float'>, got <type 'int'>
|
I'm not sure if this decorator is a good thing, or a bad thing. There are probably much more elegant ways to implement this hack.
This recipe simplifies the type checking of function arguments, and provides a part solution for some of the arguments which proponents of Statically Type Languages throw at Python.
NB: This recipe used to use the word 'Static' in place of 'Strictly'. This was confusing to some people, hence it was changed, to clarify the purpose of this recipe.
Where is static? And how exactly is this "static" when the types are checked at runtime? My (and I guess many other's) idea of static is that it is done _before_ the code has a chance to run, that is during compilation stage.
True, it's a half hearted static... This recipe only guarantees that arguments which are passed to a function are of a certain type.
It does not guarantee anything else. Perhaps using the word 'static' in the title is not strictly correct.