views:

177

answers:

4

For my program I have a lot of places where an object can be either a string or a list containing strings and other similar lists. These are generally read from a JSON file. They both need to be treated differently. Right now, I am just using isinstance, but that does not feel like the most pythonic way of doing it, so does anyone have a better way of doing it?

A: 

You can use types module:

import types
if type(ls) == types.ListType:
    #your code for list objects here
Mustafa Zengin
The preferred way of comparing types is by using `isinstance` or otherwise with the `is` operator. http://docs.python.org/library/types.html
WoLpH
Wouldn't just "type(ls) == list" work just as well?
Lars Wirzenius
You can use `type(ls) is list` however that won't work for subclasses of list
gnibbler
@Lars Wirzenius: No. That attempts to invoke a comparison of some kind, and while the default comparison for objects of type `type` is to compare object ids, and this results in identical behavior to `is`, it's not guaranteed. In this case `is` or preferably `isinstance` is the right answer.
Omnifarious
+2  A: 

Using isinstance:

On Python>=2.3 a string may be a str or unicode type. To check both cases:

if isinstance(a,basestring): # same as isinstance(obj, (str, unicode))
   print "Object is a string"

From Python 3 only one string type exists, so instead of basestring you should use str:

if isinstance(a,str):
   print "Object is a string"
zoli2k
Be careful, `unicode` is also a string. Use `basestring`.
S.Lott
S.Lott, good point. Post updated.
zoli2k
+7  A: 

No need to import modules, isinstance() and basestring (versions before 3, str and unicode for all versions including 3) will do the job for you:

Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> isinstance(u'', (str, unicode))
True
>>> isinstance('', (str, unicode))
True
>>> isinstance([], (str, unicode))
False
>>> 

From PEP008:

Object type comparisons should always use isinstance() instead of comparing types directly.

Johnsyweb
People should be discouraged from using basestring nowadays because it doesn't exist in Python 3.
Omnifarious
Is there pythonic way of doing this in Python 2 that will work in Python 3? `isinstance(u'', str)` in Python 2 returns `False`.
Johnsyweb
@Johnsyweb: you could emulate this behaviour in Python 3 with `basestring = str`. But that's about it I suppose.
WoLpH
The second argument to `isinstance` can be a tuple, so this would be better than checking against `basestring`: `isinstance(u'', (str, unicode))`
Jesse Dhillon
Thanks @Jesse, I've updated the answer.
Johnsyweb
+5  A: 

Since Python3 no longer has unicode or basestring, in this case ( where you are expecting either a list or a string) it's better to test against list

if isinstance(thing, list):
    # treat as list
else:
    # treat as str/unicode

as that is compatible with both Python2 and Python3

gnibbler
What about if `thing` is a `tuple`, a `dict` or a `set`, etcetera?
Johnsyweb
@Johnsyweb, if there was a possibility of other types then the answer would be different. This question says it is either a list or a string
gnibbler
Dear downvoter, please consider leaving a comment so I can improve my answer
gnibbler