A little stricter type checking

Andrew Dalke adalke at mindspring.com
Thu Sep 2 18:17:37 EDT 2004


Tongu? Yumruk wrote:
 > If you want to be sure, you need to explicitly check if the
 > variable has the correct type.

Rather, if you want to be sure then it's likely you
haven't fully understood "duck typing" (or "latent typing"
or "dynamic typing", depending on who you are.)  See
   http://c2.com/cgi/wiki?DuckTyping
and
   http://mindview.net/WebLog/log-0052
for more details.

In short, doing explicit type checks is not the Python way.

> Well always checking the types of the parameters in the start of every
> function is too many redundant work. Instead we can define a syntax
> that will check the type information at the beginning of function
> declaration, and even before executing any code from that function.
> That syntax might look like that:
> 
> def larry(guido >= foo):
> 	<Just actual code, no checking since the interpreter handles it>

The few times I've needed explicit type checks is to
do slightly different behaviour based on an type.
For example,

def count_lines(f):
     if isinstance(f, str):
         f = open(f, "U")
     return len(f)

Your proposal doesn't do anything for this use case.

In addition, what you're thinking of could be
done with the new "decorator" proposal.  Here's
a sketch of one way to handle it.  Ideally
it should propogate the arglist and support
keyword args and default parameters, but this
gives the essense.

 >>> class typecheck:
...   def __init__(self, *types):
...     self.types = types
...   def __call__(self, func):
...     def f(*args):
...       for arg, basetype in zip(args, self.types):
...         if not isinstance(arg, basetype):
...           raise TypeError("incompatible types")
...       return func(*args)
...     return f
...
 >>> @typecheck(int, str)
... def spam(i, s):
...     return s*i
...
 >>> spam(2, "hello")
'hellohello'
 >>> spam("hello", 2)
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 8, in f
TypeError: incompatible types
 >>>

(Wow!  My first used of the @-thingy and it worked
on the first try.)

> And if we have a function that have much more parameters, this kind of
> a syntax will really help us to remove redundant code from our
> functions. The syntax can be defined by something like:

   [
    == for exact test
    >= for superclass test
    <= for subclass test
    != for is neither subclass nor superclass
    in for attribute testing
   ]


But if you look through Python code you'll see that
most of the use cases look like my emulation of
polymorphism and not your strict type checking.  Here
are some examples from the stdlib

     def __eq__(self, other):
         if isinstance(other, BaseSet):
             return self._data == other._data
         else:
             return False



         if isinstance(instream, basestring):
             instream = StringIO(instream)



         elif (not isinstance(self.delimiter, str) or
               len(self.delimiter) > 1):
             errors.append("delimiter must be one-character string")


     if isinstance(longopts, str):
         longopts = [longopts]
     else:
         longopts = list(longopts)


        if isinstance(filenames, basestring):
            filenames = [filenames]



         if isinstance(object, types.TupleType):
             argspec = object[0] or argspec
             docstring = object[1] or ""
         else:
             docstring = pydoc.getdoc(object)

The only examples I found along the lines you wanted were
in pickletools.py, copy.py, sets.py, and warnings.py.
It just isn't needed that often in Python programming.


				Andrew
				dalke at dalkescientific.com



More information about the Python-list mailing list