File tests in Python

Alex Martelli aleaxit at yahoo.com
Fri Oct 13 18:11:29 EDT 2000


"Joakim Hove" <hove at phys.ntnu.no> wrote in message
news:k0nog0o61ko.fsf at dhcp-49138.phys.ntnu.no...
> Following up on my own post:
>
> > [...]  Writing
> >
> >    List = [1,2,["List","in","List"]]
> >
> > in Python is just the way it _should_ be, really nice!
>
> In this case List[0] and List[1] are simple scalars - whearas List[2]
> is a new list (or is this a "unPythonlike" way of thinking ??). Is
> there a way of testing this, i.e.
>
> for x in range(len(List)):
>     if is_scalar List[x]:
>         print "List[",x,"] is scalar"
>     else
>         print "List[",x,"] is not scalar - maybe a list?"

You can test the type of an object (e.g., a list entry) with the
type operator (to use symbolic names for builtin types, you
may also import module types, but it's often just as clear to
test against, e.g., type(0) for integers, type(0L) for long
integers, type([]) for lists, and so on).  Thus, one way to
do it could be:

def printType(t):
    if t==type([]): return "list"
    elif t==type(''): return "string"
    elif t==type(0): return "integer"
    elif t==type(()): return "tuple"
    else: return "something else"

for i in range(len(list)):
    print "element %d has type %s" % (i, printType(type(list[i])))

However, this kind of approach has some huge flaws -- the
number of built-in types (plus types that could be added by
the user importing C-written modules...) is enormous, and
all the _classes_ get lumped into one 'type', which you may
not want to keep as one lump...

Rather, I suggest you draw a broader distinction.  Probably,
if an object is something you can iterate on, then it's a
"sequence" (except that a string is a sequence by this
definition, as you can iterate on its characters, yet you may
prefer to treat it as 'a scalar'...); else, it could be a mapping
(typically a dictionary); or else again, "a scalar".  One
approach might then be...:

def typeClass(obj):
    t = type(obj)
    if t==type('') or t==type(u''): return 'scalar'
    elif t==type({}): return 'mapping'
    else:
        try:
            for i in obj:
                break
            return 'sequence'
        except TypeError:
            return 'scalar'

This is imperfect (no way to identify a mapping that is
not really a dictionary, e.g. an instance of UserDict --
you might want to check for that in other ways, e.g.
by checking if an object has a __getitem__ method
while not being a sequence...) but it may often serve.


Alex






More information about the Python-list mailing list