tags:

views:

1031

answers:

3

Is there a simple way to determine if a variable is a list, dictionary, or something else? Basically I am getting an object back that may be either type and I need to be able to tell the difference.

A: 

You can do that using type():

>>> a = []
>>> type(a)
<type 'list'>
>>> f = ()
>>> type(f)
<type 'tuple'>
inkedmn
+13  A: 
>>> type( [] ) == list
True
>>> type( {} ) == dict
True
>>> type( "" ) == str
True
>>> type( 0 ) == int
True
>>> class Test1 ( object ):
    pass
>>> class Test2 ( Test1 ):
    pass
>>> a = Test1()
>>> b = Test2()
>>> type( a ) == Test1
True
>>> type( b ) == Test2
True
>>> type( b ) == Test1
False
>>> isinstance( b, Test1 )
True
>>> isinstance( b, Test2 )
True
>>> isinstance( a, Test1 )
True
>>> isinstance( a, Test2 )
False
>>> isinstance( [], list )
True
>>> isinstance( {}, dict )
True

edit: Updated to add some more custom tests.

poke
What a fast typist :)
telliott99
I think it's clearer to use `is` instead of `==` as the types are singletons
gnibbler
Fair enough ;) But I think the idea got through :)
poke
@gnibbler, In the cases you would be typechecking (which you shouldn't be doing to begin with), `isinstance` is the preferred form anyhow, so neither `==` or `is` need be used.
Mike Graham
@Mike Graham, there are times when `type` is the best answer. There are times when `isinstance` is the best answer and there are times when duck typing is the best answer. It's important to know all of the options so you can choose which is more appropriate for the situation.
gnibbler
@gnibbler, That may be, though I haven't yet ran into the situation where `type(foo) is SomeType` would be better than `isinstance(foo, SomeType)`.
Mike Graham
I used constructs like `type( param ) in ( list, tuple )` in the past, when working with different parameter types, where a completely different approach was required based on the type.
poke
+7  A: 

It might be more Pythonic to use a try...except block. That way, if you have a class which quacks like a list, or quacks like a dict, it will behave properly regardless of what its type really is.

To clarify, the preferred method of "telling the difference" between variable types is with something called duck typing: as long as the methods (and return types) that a variable responds to are what your subroutine expects, treat it like what you expect it to be. For example, if you have a class that overloads the bracket operators with getattr and setattr, but uses some funny internal scheme, it would be appropriate for it to behave as a dictionary if that's what it's trying to emulate.

The other problem with the type(A) is type(B) checking is that if A is a subclass of B, it evaluates to false when, programmatically, you would hope it would be true. If an object is a subclass of a list, it should work like a list: checking the type as presented in the other answer will prevent this. (isinstance will work, however).

Seth Johnson