Jump to content
  • Advertisement
Sign in to follow this  

Some type checking in Python

This topic is 4102 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been playing around with the idea of adding some run-time typechecking in Python, just for debugging purposes. That is, type-checking is only on during the development of the program, and probably disabled when it's about to be released for the users. I've come up with a simple module that handles most of this, so I thought I shared. First things first, this is the module: safe.py
import types

#just for some convenience...

def safe(*sig):
    def _f(f):
        return func
    return _f

#Uncomment the below if you want to disable type-checking entirely(even if the func is decorated as @safe)
def safe(*sig):
    def _f(f):
        return f
    return _f

def partial(f,*bind_args):
    def _f(*args):
        return f(*(bind_args+args))
    return _f   
def safecall(f,sig,*args):
    #check arguments
    for (arg,typ) in zip(args,sig[0:l-1]):
        if not isinstance(arg,typ):
            raise TypeError,"Incorrect type of arg"+str(i)+":expected "+str(typ)+" got "+str(type(arg))+" instead"
    #check result    
    if not isinstance(result,sig[l-1]):
        raise TypeError,"Wrong result type: expected"+str(sig[l-1])+" got "+str(type(result))+" instead"
    return result

The idea is that you use the decorator @safe to give a function a signature. So, if the function accepts two ints and returns a bool, the decorator will be: @safe(int,int,bool) Instead of one type, you can define a tuple of types the arguments will be checked against. To make the above function work for any kind of number(int,long,float), you just do: number=(int,long,float) @safe(number,number,bool) Of course, inheritence rules are applied during type checking.Also,if you don't want to type-check a specific argument, and want it to accept any type, you can use the generic object type. What's more, the function/method gets a "sig" member that contains the "signature" as defined in the decorator. So you can just do "print foo.sig" for a @safe "foo" function to inspect the types of arguments and result it expects. The below code demonstrates in more detail the use of the module(it supports methods too).
from safe import *
from types import *

def add_numbers(x,y):
    return x+y

def concat(s1,s2):
    return s1+s2

class Foo(object):
    def __init__(self,name,x,lst):

#Print some signatures...
print "add_numbers:",add_numbers.sig
print "concat:",concat.sig
print "Foo.__init__:",Foo.__init__.sig
#All these are legal:
print add_numbers(2,3)
print concat("Hello ","world")

#All these produce exceptions:        
#print add_numbers(2,"Hello")
#print concat(1,2)

I hope some at least Pythonistas will find it useful to make the debugging sessions somewhat easier. Also, don't be afraid to leave the comment if you think this idea and module are just awful ;)

Share this post

Link to post
Share on other sites
Guest Anonymous Poster
kind of reminds me of this ;)

Share this post

Link to post
Share on other sites
Guest Anonymous Poster
Ah... I tried to link to this:

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!