A Suggestion (please read and respond)

Alex Martelli aleaxit at yahoo.com
Mon Oct 30 18:17:46 EST 2000


"Franz GEIGER" <fgeiger at datec.at> wrote in message
news:8tk3so$fvm$1 at newsreaderm1.core.theplanet.net...
> Indeed, typos are very annoying and I hate to find them at runtime.
> In a 1st step a kind of a lint program would do.

There are several "lint for Python" scripts on the net, of
course.  But Python is good enough at 'introspection'
that not much is needed for a task such as checking
that a function has "declared" all local variables it
defines, for example -- supposing, for example, that
you decide you want the 'declaration' to be a line in
the function's docstring, of the form, say:

    local: a, b,c,d


For any function object f, the list of its local
variable names (arguments excluded, assuming
you don't want arguments to have to be declared
as well) is easy to find -- let's sort it alphabetically,
too, as long as we're at it:

def localnamesof(f):
    "local: co, result"
    co=f.func_code
    result=list(co.co_varnames[co.co_argcount:])
    result.sort()
    return result

as are the lines in its docstring that are of the
above 'local-declaration form':

def declaredof(f):
    "local: result, line, words"
    result=[]
    for line in f.__doc__.split('\n'):
        words=line.split()
        if words and words[0]=='local:':
            result.extend(''.join(words[1:]).split(','))
    result.sort()
    return result

Now we have the list of local names defined in
the function, localnamesof(f), and that of those
declared in 'local:' lines -- and they're already
sorted, too, so we just need to check equality:

def checklocals(f):
    defined=localnamesof(f)
    declared=declaredof(f)
    if declared==defined: return 1
    return 0

Of course, it's easy to give better diagnostics
if the check fails, and information about those
variable names if it succeeds; one may also
choose to implement a specific declaration
    args: x, y
in addition, etc, etc.


Then, one gets into the _global_ variables
business -- which is trickier for compile-time
control, since the global variables are only
first set when the module is imported (and
so its global code executed), and others may
be added later arbitrarily (even from outside
the module).  If we're OK with checking after
import and don't care about highly dynamic
behavior such as the latter, it's not too bad.

Variables are going to be the entries in the
module's directory (excepting those of type
function and class, and the intrinsic ones such
as __doc__ etc) -- those are easier to get.

A bit trickier is taking into account that any
function of the module may create or use
variables there; but the co_names attribute
of the functions' (and methods'...) code
objects can help (with some care about those
names which are not of global variables, but
of local ones, built-ins, functions, ...).


I think it's a good exercise to extend this --
and, worst case, one starts to play with the
modules in section 17 of the Library
Reference...

If you try this, I predict you may have a much
better grasp (and appreciation) of Python
once you're done.  Probably enough to agree
with me that the result has little practical use...
but, it _has_ been instructive to develop!-)


Alex






More information about the Python-list mailing list