Test for structure

Martin Miller ggrp1.20.martineau at dfgh.net
Mon Feb 21 03:33:23 EST 2005


Yes, both string and lists have a __getitem__ attribute:

>>> c1 = 'abc'
>>> c2 = ['de', 'fgh', 'ijkl']
>>> hasattr(c1, '__getitem__')
True
>>> hasattr(c2, '__getitem__')
True

In other words you could index elements of either one using [].

Likewise, both a string and list would produce a usable iterator using
the following logic:

try:
    itr = iter(a)
except TypeError:
    # 'a' is not iterable
else:
    # 'a' is iterable

In either case, you can't tell a string and list apart, which is what
the OP wanted to know, namely how to differentiate the two. EAPF is
fine, but what operation would answer the string vs list question?

Perhaps the test for an __iter__ attribute *is* the way to go because
you can tell the difference between the two type. Again I don't know
because the OP doesn't give enough information. I suspect, but don't
know, that it could be so that either one string or a list of strings
as an argument could treated as a list of 0 or more strings and
accessed by indices by most of the rest of the code.

I think the technique suggested by Robin Munn nearly a year ago (and
referenced by the link in Simon Brunning's post):
http://groups-beta.google.com/group/comp.lang.python/msg/c8befd4bed517bbc
namely:

try:
    a + ''
except TypeError:
    pass
else:
    a= [a]

would be a good usable solution, although it's not totally infallible.
It may not be possible to give a better answer without more real
information about the desired usage.

Martin


=====================
Steven Bethard wrote:
> Terry Hancock wrote:
>  > But you probably shouldn't do that. You should probably just test
to
>  > see if the object is iterable --- does it have an __iter__ method?
>  >
>  > Which might look like this:
>  >
>  > if hasattr(a, '__iter__'):
>  >     print "'a' quacks like a duck"
>
> Martin Miller top-posted:
> > I don't believe you can use the test for a __iter__ attribute in
this
> > case, for the following reason:
> >
> >>>>c1 = 'abc'
> >>>>c2 = ['de', 'fgh', 'ijkl']
> >>>>hasattr(c1, '__iter__')
> > False
> >
> >>>>hasattr(c2, '__iter__')
> > True
>
> Right.  str and unicode objects support iteration through the old
> __getitem__ protocol, not the __iter__ protocol.  If you want to use
> something as an iterable, just use it and catch the exception:
>
> try:
>      itr = iter(a)
> except TypeError:
>      # 'a' is not iterable
> else:
>      # 'a' is iterable
>
> Another lesson in why EAPF is often better than LBYL in Python[1].
> 
> STeVe
> 
> [1] http://www.python.org/moin/PythonGlossary




More information about the Python-list mailing list