473,396 Members | 1,772 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Test for structure

Hi there,

how can I check if a variable is a structure (i.e. a list)? For my
special problem the variable is either a character string OR a list of
character strings line ['word1', 'word2',...]

So how can I test if a variable 'a' is either a single character string
or a list? I tried:

if a is list:
but that does not work. I also looked in the tutorial and used google
to find an answer, but I did not.

Has anyone an idea about that?

Alex

Jul 18 '05 #1
18 1837
import types

v = []
if type(v) is types.ListType:
pass
--
Regards,

Diez B. Roggisch
Jul 18 '05 #2
On Wed, 16 Feb 2005 07:11:08 -0800 (PST), alex
<al*************@mpi-hd.mpg.de> wrote:
how can I check if a variable is a structure (i.e. a list)? For my
special problem the variable is either a character string OR a list of
character strings line ['word1', 'word2',...]

So how can I test if a variable 'a' is either a single character string
or a list? I tried:

if a is list:

but that does not work. I also looked in the tutorial and used google
to find an answer, but I did not.

Has anyone an idea about that?


<http://www.brunningonline.net/simon/blog/archives/001349.html>

--
Cheers,
Simon B,
si***@brunningonline.net,
http://www.brunningonline.net/simon/blog/
Jul 18 '05 #3
Perhaps you're looking for the type() built in function and the types modules?
type('aaa') <type 'str'> type([]) <type 'list'> import types
if type([]) is types.ListType:
.... print 'is a list'
....
is a list

Chris

On Wed, 16 Feb 2005 07:10:56 -0800 (PST), alex
<al*************@mpi-hd.mpg.de> wrote: Hi there,

how can I check if a variable is a structure (i.e. a list)? For my
special problem the variable is either a character string OR a list of
character strings line ['word1', 'word2',...]

So how can I test if a variable 'a' is either a single character string
or a list? I tried:

if a is list:

but that does not work. I also looked in the tutorial and used google
to find an answer, but I did not.

Has anyone an idea about that?

Alex

--
http://mail.python.org/mailman/listinfo/python-list

--
"It is our responsibilities, not ourselves, that we should take
seriously." -- Peter Ustinov
Jul 18 '05 #4
alex wrote:
So how can I test if a variable 'a' is either a single character string
or a list?


py> def test(x):
.... return (isinstance(x, list) or
.... isinstance(x, basestring) and len(x) == 1)
....
py> test('a')
True
py> test('ab')
False
py> test([])
True
py> test(['a', 'b'])
True

But definitely read Simon Brunning's post - you probably don't actually
want to do this test. Why do you think you want to test this? What's
your use case?

STeVe
Jul 18 '05 #5
I use a function isListLike in cases such as this one:

# def isListLike(L):
# """Return True if L is list-like, False otherwise."""
# try:
# L + []
# return True
# except:
# return False

Then you can use a standard if-else construct:

# if isListLike(myvar):
# <do something>
# else:
# <do something else>

Michael

--
Michael D. Hartl, Ph.D.
Chief Technology Officer
http://quarksports.com/

Jul 18 '05 #6
Michael Hartl wrote:
I use a function isListLike in cases such as this one:

# def isListLike(L):
# """Return True if L is list-like, False otherwise."""
# try:
# L + []
# return True
# except:
# return False

Then you can use a standard if-else construct:

# if isListLike(myvar):
# <do something>
# else:
# <do something else>


What kind of situations do you use this for? I almost never have to do
this kind of typechecking. If it's supposed to be a list, I just use it
as a list...

STeVe
Jul 18 '05 #7
alex wrote On 17/02/05 02:08:
how can I check if a variable is a structure (i.e. a list)? For my
special problem the variable is either a character string OR a list
of character strings line ['word1', 'word2',...]


You're trying to apply the LBYL principle. My bet is that your "special
problem" can be solved by the EAFP principle. (These terms are
explained in the Glossary of the tutorial,
<http://www.python.org/doc/current/tut/node18.html>.)

If you test for a specific set of types, your code will not work with
types that you have not considered yet behave like lists. As you
discover more object types that you want the code to work with, it will
sprout more cruft for checking those types.

If you want to use some list behaviour of the object, don't check first.
Use it, and catch the TypeError exception in the event that it's not.
This way, *any* object that implements the functionality you need will
work, regardless of its type.
Jul 18 '05 #8
On Wednesday 16 February 2005 09:08 am, alex wrote:
how can I check if a variable is a structure (i.e. a list)? For my
special problem the variable is either a character string OR a list of
character strings line ['word1', 'word2',...]

So how can I test if a variable 'a' is either a single character string
or a list?


The literally correct but actually wrong answer is:

if type(a) == type([]):
print "'a' is a duck"

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"

That way your function will also work if a happens to be a tuple,
a dictionary, or a user-defined class instance which is happens to
be iterable.

Being "iterable" means that code like:

for i in a:
print "i=%s is an element of a" % repr(i)

works. Which is probably why you wanted to know, right?

Cheers,
Terry

--
--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com

Jul 18 '05 #9
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 for i in c1: print "i=%s is an element of c1" % repr(i)
....
i='a' is an element of c1
i='b' is an element of c1
i='c' is an element of c1

In other words, even though the c1 single string variable does not have
an __iter__ attribute, it can still be used in a for loop. I think the
right answer would depend on what exactly the OP intends to do with the
argument when it is a list (or is list-like in some way) -- i.e. he
didn't say specifically that he wanted use it in a for loop.

-Martin
====================
Terry Hancock wrote:
On Wednesday 16 February 2005 09:08 am, alex wrote:
how can I check if a variable is a structure (i.e. a list)? For my
special problem the variable is either a character string OR a list

of character strings line ['word1', 'word2',...]

So how can I test if a variable 'a' is either a single character string or a list?


The literally correct but actually wrong answer is:

if type(a) == type([]):
print "'a' is a duck"

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"

That way your function will also work if a happens to be a tuple,
a dictionary, or a user-defined class instance which is happens to
be iterable.

Being "iterable" means that code like:

for i in a:
print "i=%s is an element of a" % repr(i)

works. Which is probably why you wanted to know, right?

Cheers,
Terry

--
--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com


Jul 18 '05 #10
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
Jul 18 '05 #11
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/...befd4bed517bbc
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


Jul 18 '05 #12
> Steven Bethard wrote:

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

Martin Miller broke the order of reading by top-posting: 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.
Yes, sorry, I should have marked my post OT. It was an answer to Terry
Hancock's post suggesting hasattr(x, '__iter__'), not the OP.
Perhaps the test for an __iter__ attribute *is* the way to go because
you can tell the difference between the two type.
I've seen this done before, e.g.:

try:
itr = iter(x)
except TypeError:
# is not iterable
else:
if hasattr(x, '__iter__'):
# is other iterable
else:
# is str or unicode

I don't like this idea much because it depends on str and unicode _not_
having a particular function. I haven't seen any guarantee anywhere
that str or unicode won't ever grow an __iter__ method. So this code
seems dangerous as far as future compatibility goes.
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/...befd4bed517bbc
namely:

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

would be a good usable solution, although it's not totally infallible.


Yup, if I had to do this kind of type-checking (which I don't think I
ever do), I'd probably go with something along these lines.

STeVe
Jul 18 '05 #13
Testing for the '__iter__' (or even '__getitem__') attribute doesn't
really address the problem, nor does trying to execute the statement
'itr = iter(a)'.

To use EAPF and answer the OP's original question, which was
So how can I test if a variable 'a' is either a single character
string or a list?
I think the best answer would be to use Robin Munn's suggestion (see
http://groups-beta.google.com/group/...befd4bed517bbc)
as mentioned in the link in Simon Brunning's post) namely:

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

However, to handle the more general problem of allow *any* argument to
be either a single item or a list seems to require a combination of
both EAPF and LBYL. This is the best solution I've been able to come up
with so far:

def asList(arg):
"""Makes sure the argument it is passed is a Python list.
If it is, it is just returned, otherwise a (possibly empty)
list is created and returned with the single item in it.

asList() can used to create flexible interfaces which allow
arguments to be passed to them that are either single items or
lists of items. By applying this function before using the
values in arguments, single and multi-valued cases can be
handled by general list-handling code in the function or
method.

As a special case, a single argument with the value None is
converted into an empty list (instead of converted into the
list [None]).

asList(arg) ==> list
"""

if arg is None:
return []
elif isinstance(arg, basestring): # special case strings (to
# avoid list(<string>))
return [arg]
else:
try:
return list(arg)
except TypeError:
return [arg]
if __name__ == "__main__":

def example(items=None):
"""Sample function that can be called with a single argument
that can be a single or list of items.
"""
itemList = asList(items)
if not itemList:
print "example() called with empty list or None argument"
else:
print "example() called with argument containing %d " \
"thing%s" % \
(len(itemList), ('','s')[len(itemList)>1])
for i, item in enumerate(itemList):
print " items[%d] = %s" % (i, repr(item))

example(42)
example((1,2,3))
example([4,5,6,7])
example('abc')
example(u'def')
example(["aaa", 111, (4,5), 2.01])
example(None) # Note that this will become an empty list
example() # same in this case

Which produces the following output:

example() called with argument containing 1 thing
items[0] = 42
example() called with argument containing 3 things
items[0] = 1
items[1] = 2
items[2] = 3
example() called with argument containing 4 things
items[0] = 4
items[1] = 5
items[2] = 6
items[3] = 7
example() called with argument containing 1 thing
items[0] = 'abc'
example() called with argument containing 1 thing
items[0] = u'def'
example() called with argument containing 4 things
items[0] = 'aaa'
items[1] = 111
items[2] = (4, 5)
items[3] = 2.0099999999999998
example() called with empty list or None argument
example() called with empty list or None argument

Can this be improved or is there anything wrong or overly limiting
about it?

TIA,
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


Jul 18 '05 #14
Martin Miller broke the order of reading again by top-posting:
However, to handle the more general problem of allow *any* argument to
be either a single item or a list seems to require a combination of
both EAPF and LBYL. This is the best solution I've been able to come up
with so far:

def asList(arg): [snip] if arg is None:
return []
elif isinstance(arg, basestring): # special case strings (to
# avoid list(<string>))
return [arg]
else:
try:
return list(arg)
except TypeError:
return [arg]
[snip] Can this be improved or is there anything wrong or overly limiting
about it?


I don't think you're going to do a whole lot better than that, though
you can try something like the following if you're really afraid of the
isinstance:

def aslist(arg):
# you don't need to test None; it will be caught by the list branch
try:
arg + ''
except TypeError:
return [arg]
try:
return list(arg)
except TypeError:
return [arg]

That said, I find that in most cases, the better option is to use *args
in the original function though. For example:

def f(arg):
args = aslist(arg)
...
f(42)
f(['spam', 'eggs', 'ham'])

could probably be more easily written as:

def f(*args):
...
f(42)
f('spam', 'eggs', 'ham')

Of course this won't work if you have multiple list arguments.

STeVe
Jul 18 '05 #15

"Steven Bethard" <st************@gmail.com> wrote in message
news:Gv********************@comcast.com...
I don't like this idea much because it depends on str and unicode _not_
having a particular function. I haven't seen any guarantee anywhere that
str or unicode won't ever grow an __iter__ method. So this code seems
dangerous as far as future compatibility goes.


When CPython's support for the old iteration protocol goes away, which I
expects it will someday, strings will have to grow an __iter__ method.
Even now, I think this difference between strings and lists is more of an
accident than a logical design. So the test is opaque and specific to
current CPython. The validity of something like a = a+'', however, is
inherent to the nature of strings.

Terry J. Reedy

Jul 18 '05 #16
At the end of his last post, Steve Bethard wrote:
That said, I find that in most cases, the better option is to use *args in the original function though. For example:

def f(arg):
args = aslist(arg)
...
f(42)
f(['spam', 'eggs', 'ham'])

could probably be more easily written as:

def f(*args):
...
f(42)
f('spam', 'eggs', 'ham')

Of course this won't work if you have multiple list arguments.


Very interesting, but it also doesn't let you specify a default
argument value...however this gave me the idea that it would be
possible to use the *args idea to greatly simplify the proposed
aslist() function -- when one was needed to allow default argument
values and/or for handling multiple list arguments. Namely:

def aslist(*args):
return list(args)

def f(arg=None):
args = aslist(arg)
...

f()
f(42)
f('tanstaafl')
f(['spam', 'eggs', 'ham'])

This seems fairly lean and mean, with no if, isinstance, hasattr, or
try/excepts required -- although aslist() might need a check for the
single argument of None case, depending on whether it should return []
or something besides [None] in that situation.

Best,
Martin

Jul 18 '05 #17
Ooops. I left out an "*" on a statement in the new aslist() function. I
should have written:

def aslist(*args):
return list(*args) # corrected

def f(arg):
args = aslist(arg)
...

Sorry,
Martin

Jul 18 '05 #18
Nope, that isn't right either, in the sense that it handles all the
cases properly, including "single string" vs "list of strings'. Guess
this overly simplistic aslist() does not work after. I should have been
more suspicious and cautious before posting. Sorry.

Martin

Jul 18 '05 #19

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Dave Smithz | last post by:
Hi There, I have taken over someone else's PHP code and am quite new to PHP. I made some changes and have implemented them to a live environment fine so far. However, I now want to setup a...
4
by: Edvard Majakari | last post by:
Hi, I just found py.test and converted a large unit test module to py.test format (which is actually almost-no-format-at-all, but I won't get there now). Having 348 test cases in the module and...
41
by: Roy Smith | last post by:
I've used the standard unittest (pyunit) module on a few projects in the past and have always thought it basicly worked fine but was just a little too complicated for what it did. I'm starting a...
2
by: B. Wood | last post by:
I have written a simple program the has a structure with two members. There are two strange things going on. 1. When on of the structure members is tested in a condition, the value of the...
2
by: Netkiller | last post by:
#!/usr/bin/python # -*- coding: utf-8 -*- """ Project: Network News Transport Protocol Server Program Description: 基于数据库的新闻组,实现BBS前端使用NNTP协议来访问贴子...
9
by: Deckarep | last post by:
Hello Group, I actually have two seperate questions regarding Unit Testing with NUnit in C#. Please keep in mind that I'm new to the concept of Unit Testing and just barely coming around to...
0
by: Alan Isaac | last post by:
This is really a repackaging of an earlier question, probably illustrating that I still do not understand relative imports. Suppose I have the package structure (taken from the example at...
4
by: melissa86 | last post by:
My son needs to take a computer test to take an on-line class. He knows what most everything is except for the following. I have no idea about this myself unless they are just using terms I am not...
2
by: =?Utf-8?B?c2lwcHl1Y29ubg==?= | last post by:
I was wonder if there is any protocol or suggestions on how to setup unit testing projects in large solution??? If you have a large solution of say 50 projects and add a project for every unit...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development projectplanning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.