detecting variable types

J

Jay

I'm sure this is a really dumb question, but how do you detect a variable
type in Python?

For example, I want to know if the variable "a" is a list of strings or a
single string. How do I do this?
 
P

Peter Hansen

Jay said:
I'm sure this is a really dumb question, but how do you detect a variable
type in Python?

For example, I want to know if the variable "a" is a list of strings or a
single string. How do I do this?

Use the builtin function "type()", but note the following:

1. Variables don't actually have types in Python (and they're usually
called "names" in Python, for various reasons), but the data they are
currently bound to does have a type and that's what type() returns.
Often the distinction won't matter to you...

2. Most of the time people trying to do what you are probably trying
to do are going about things the wrong way, often from experience
with other languages. Lots of Python folks would be happy to introduce
you to "better" ways to do things, if you'll explain the use case
and tell us what you're actually trying to accomplish. (Of course,
using "type()" will work, but it's rarely considered the best
approach in the Python community.)

-Peter
 
C

Chris Green

Jay said:
I'm sure this is a really dumb question, but how do you detect a variable
type in Python?

For example, I want to know if the variable "a" is a list of strings or a
single string. How do I do this?
<type 'int'>

you should look at the types module as well
True
 
J

Jay

Thanks, Peter.

Here's what I'm trying to do:

I have a function like this:

def func(**params):

# if params[key1] is a single string
# do something with params[key1]

# if params[key1] is a list of strings
for val in params[key1]:
# do something

Could you suggest a better way to do this without detecting the type?


Jay.
 
D

djw

Jay said:
Thanks, Peter.

Here's what I'm trying to do:

I have a function like this:

def func(**params):

# if params[key1] is a single string
# do something with params[key1]

# if params[key1] is a list of strings
for val in params[key1]:
# do something

Could you suggest a better way to do this without detecting the type?


Jay.


Peter Hansen said:
Use the builtin function "type()", but note the following:

1. Variables don't actually have types in Python (and they're usually
called "names" in Python, for various reasons), but the data they are
currently bound to does have a type and that's what type() returns.
Often the distinction won't matter to you...

2. Most of the time people trying to do what you are probably trying
to do are going about things the wrong way, often from experience
with other languages. Lots of Python folks would be happy to introduce
you to "better" ways to do things, if you'll explain the use case
and tell us what you're actually trying to accomplish. (Of course,
using "type()" will work, but it's rarely considered the best
approach in the Python community.)

-Peter


One obvious way, in this case is to always pass in a list of strings. A
single string would be passed in as a list with a single string item in it.

def func( stringlist ):
for s in stringlist:
#do something with s

func( [ "single string" ] )
func( [ "more", "than", "one", "string" ] )

Other than that, if the functions are really doing something very different
given different parameter types, then I would make separate functions.

-Don
 
J

John Roth

Jay said:
Thanks, Peter.

Here's what I'm trying to do:

I have a function like this:

def func(**params):

# if params[key1] is a single string
# do something with params[key1]

# if params[key1] is a list of strings
for val in params[key1]:
# do something

Could you suggest a better way to do this without detecting the type?

I'd strongly suggest making the value of "key1" a list in
all cases, including the case where there is no value:
that is, an empty list.

It makes your processing logic a lot simpler, and even if
you can't make the caller do it that way, the function/method
to preprocess is fairly simple (and also takes care of the
"key not found" case.)

John Roth
 
T

Tuure Laurinolli

Jay said:
def func(**params):

# if params[key1] is a single string
# do something with params[key1]

# if params[key1] is a list of strings
for val in params[key1]:
# do something

Could you suggest a better way to do this without detecting the type?

def func_for_string(astring):
pass

def func_for_a_list_of_strings(alist):
pass


Also, top posting is evil. See
http://www.cs.tut.fi/~jkorpela/usenet/brox.html
 
A

Andrew Koenig

Here's what I'm trying to do:

I have a function like this:

def func(**params):

# if params[key1] is a single string
# do something with params[key1]

# if params[key1] is a list of strings
for val in params[key1]:
# do something

Could you suggest a better way to do this without detecting the type?

I don't see anything particularly wrong with detecting the type this way:

if isinstance(params[key1], list):
for val in params[key1]:
# do something
else:
# do something with params[key1]

Of course that won't work for other kinds of sequences, but if that's what
you want, then that's what you want.
 
G

Grant Edwards

Here's what I'm trying to do:

I have a function like this:

def func(**params):

# if params[key1] is a single string
# do something with params[key1]

# if params[key1] is a list of strings
for val in params[key1]:
# do something

Could you suggest a better way to do this without detecting the type?

I don't see anything particularly wrong with detecting the type this way:

if isinstance(params[key1], list):
for val in params[key1]:
# do something
else:
# do something with params[key1]

Of course that won't work for other kinds of sequences, but if that's what
you want, then that's what you want.

When I write functions that accept either a list or a single
object, I usually "normalize" the paramter into a list and then
the rest of the function just operates on lists:

if not isinstance(myParameter,list):
myParameter = [myParameter]

[...]

for p in myParameter:
<do whatever>

[...]
 
B

Bengt Richter

Thanks, Peter.
Please don't top-post, ok? Notice what it does to the order
of your comments and mine vs Peters'. Insert your comments below
quoted material it refers to, then order can be preserved through
several generations. Stacking wholes monolithically preserves order
too, but it gets harder to indicate where in the following monoliths
your top-posted comments apply.
Here's what I'm trying to do:

I have a function like this:

def func(**params):

# if params[key1] is a single string
# do something with params[key1]

# if params[key1] is a list of strings
for val in params[key1]:
# do something

Could you suggest a better way to do this without detecting the type?
That particular distinction is extra nasty because strings are also iterable.

One trouble with type(arg)==list or type(arg)==str is that if your calling
program wants to pass a list or str subtype later, you will have to change
your func code to detect the new type, even though it behaves the same.

So you usually better off with an isinstance(arg, str) than a type(arg)==str test.
Notice,
True

IOW, False

Sometimes you do actually need that distinction though.

Regards,
Bengt Richter
 
B

Byron

Hi Jay,

You can detect the type of a variable by using the "types" module that
comes with Python. Here is how to use it:


>>> import types
>>> name = "Steven"
>>> if type(name) is types.StringType:
print "Yes, name is a string."


Hope this helps,

Byron
 
S

Scott David Daniels

Byron said:
Hi Jay,

You can detect the type of a variable by using the "types" module that
comes with Python. Here is how to use it:


print "Yes, name is a string."


Hope this helps,

Byron

If you must switch on the type, use something like:

...
if isinstance(vbl, (string, unicode)):
vbl = [vbl]
for element in vbl:
...

There are many more kinds of iterables than kinds of strings,
and you'll get fewer surprises with the above.

-Scott David Daniels
(e-mail address removed)
 
A

Alex Martelli

Andrew Koenig said:
I don't see anything particularly wrong with detecting the type this way:

if isinstance(params[key1], list):

Better than checking type(...), but then, a lesser evil need not be
'right'.
Of course that won't work for other kinds of sequences, but if that's what
you want, then that's what you want.

Sometimes people want what's not best for them, and sometimes they
believe they want something, but really don't. If somebody asks me
about how best to shoot his own foot, I may perhaps suggest weapon types
and suitable ammunition, but often I'd add some note about the problems
that often result by shooting one's own foot, even with the most
suitable choice of ammunition and weapon. ((Come on -- if somebody
asked __in a C++ group__ how best to code the equivalent of...:

if(is_circle(x)) draw_circle(x);
else if(is_square(x)) draw_square(x);
...
would you just mention how dynamic_cast may be used for the purpose,
without one word as to how a polymorphic x.draw() is better...?-))

Nevertheless, singling out _strings_ from other kinds of sequences and
iterables IS unfortunately needed sometimes. That's why built-in type
basestring exists: for the sole reason of allowing a typetest of the
form "if isinstance(whatever, basestring):...". Once strings (byte and
unicode kinds) are out of the way, all other sequences and iterables can
often be treated uniformly and polymorphically with a for loop or
whatever. A frequent idiom:

if isinstance(whatever, basestring):
whatever = [whatever]
try: whatever = iter(whatever)
except TypeError: whatever = iter([whatever])
for item in whatever:
...

this deals sensibly with being passed any iterable (singling out strings
as scalars even though they're iterable) OR any non-iterable (to be
treated as the equivalent singleton-iterable with that one item only).


Alex
 
A

Alex Martelli

Scott David Daniels said:
if isinstance(vbl, (string, unicode)):

Nope! Use isinstance(vbl, basestring) instead. basestring exists for
that one and only reason... besides str (not 'string') and unicode, any
user-coded type that _wants_ to be "treated as a string for all intents
and purposes" may choose to inherit from basestring instead of object
(it's supposed to get no effect whatsoever from that _except_ from code
that does this specific kind of typechecking specifically).


Alex
 
E

Egbert Bouwman

On page 208 in the cookbook Alex seems to say that the Borg class
should be subclassed. I don't see the necessity.
Just take the original four-lined Borg(), give it a suitable name,
maybe add some arguments, add oher methods, and instantiate it.
Or am I missing something again ?
egbert
 
A

Alex Martelli

Egbert Bouwman said:
On page 208 in the cookbook Alex seems to say that the Borg class
should be subclassed. I don't see the necessity.
Just take the original four-lined Borg(), give it a suitable name,
maybe add some arguments, add oher methods, and instantiate it.
Or am I missing something again ?

If you need two classes with "singleton-like behavior", implementing
them as subclasses of Borg is preferable to "copy and paste ``reuse''"
for much the same reason real reuse is always preferable to c&p reuse,
whenever feasible. Should there ever be any useful maintenance to Borg
(e.g., make it a newstyle class, optimize it in some other way,
whatever!), if you have reused it properly you're in clover; if you have
copied and pasted, you're not. As usual, there are _no_ compensating
advantages for "copy and paste ``so-called reuse''" whatsoever.

_Once, and ONLY once_. ANY TIME you have the same functionality coded
twice, in two places, in two copies, that should raise your hackles.
Train yourself to feel DISGUST at such cases, and remove them
immediately whenever you observe them, in favour of a "once and only
once" occurrence of the functionality, reused in two or more places in
the proper ways (function calls, class instantiation, inheritance,
whatever). You'll be MUCH happier as a result of such a stance,
throughout your programming career.


Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top