15

I found this 3 ways to check it, but I don't know which of them is the best:

x = ['Bla', 'Bla', 'Bla', 'etc']

if isinstance(a, list): print('Perfect!')
if type(a) is list:     print('Incredible!')
if type(a) == type([]): print('Awesome!')

Which of these is better?

Also, Can I use these ways to check whether an x is a string, tuple, dictionary, int, float, etc? If this is possible, in the first two methods do I have to convert a list to a tuple, string, dictionary, int, float, etc (no?), but in the third? I have to use (), {}, '', and what more for int and float?

Ender Look
  • 2,303
  • 2
  • 17
  • 41

3 Answers3

34

These all express different things, so really it depends on exactly what you wish to achieve:

  • isinstance(x, list) check if the type of x is either list or has list as a parent class (lets ignore ABCs for simplicity etc);
  • type(x) is list checks if the type of x is precisely list;
  • type(x) == list checks for equality of types, which is not the same as being identical types as the metaclass could conceivably override __eq__

So in order they express the following:

  • isinstance(x, list): is x like a list
  • type(x) is list: is x precisely a list and not a sub class
  • type(x) == list: is x a list, or some other type using metaclass magic to masquerade as a list.
donkopotamus
  • 22,114
  • 2
  • 48
  • 60
  • Sorry but i am a quite noob, i only could understand the second: **"type(x) is list"**. "check if the type of x is either list or has list **as a parent class** ¿parent class? ¿Is something about classes (i don't know almost nothing about that)?. And 'checks for **equality** of types, which is not the same as being **identical** types as...', sorry but what is a equality of types but not identical types?. If i want to check a 'simple list' (nothing about class or something advanced), my best way (less complicated or advanced) is to use **"type(x) is a list'**? – Ender Look Mar 30 '17 at 01:45
2

Do you need to know if it's a list, or just if it's iterable (if you can use it in a for loop, for example)? Generally the "Pythonic way" is to just go ahead and do it in a try-except, because many things can be iterable: strings, lists, sets, deques, custom types, etc. (All it takes is an __iter__ or __getitem__ method)

If you REALLY need to know what type it is, isinstance() is typically the way to go since it will also cover subclasses.

As far as using type() == something is concerned, int, float, list, etc are all types: type(1) == int is True.

My typical approach, where I might have a string, a list (or tuple, etc.) of strings, or an int or other object which can be converted to a string, would be this (for Python 2 - Py3 no longer has basestring so you'll need to check for str and/or bytes), assuming foo is your variable:

if isinstance(foo, basestring):
    foo = (foo,) # turn it into an iterable (tuple)
    # or, doStuff(foo) followed by a return or break
try:
    for x in foo:
        doStuff(str(x)) # do something with each element
except TypeError: # TypeError: 'some' object is not iterable
    doStuff(str(foo))
DimeCadmium
  • 168
  • 7
  • Thanks for the advice, but i have to do the check really, because if my argument in the function is a list it will do something like 'for x in list: print(x)', and if the argument is a string it will only do: print(argument). – Ender Look Mar 30 '17 at 02:26
  • 1
    In that case, I would test if it's a string instead. Only two things are a string (bytes and string in Py3; string and unicode in Py2). Many things are iterable (lists, tuples, sets, deques, custom objects). In a similar situation I've done this by testing if it's a string, if not it goes to a for loop in a try, then the except block checks if I can call str() on it (i.e. if it has a __str__). – DimeCadmium Apr 02 '17 at 01:10
  • Tring to improve my code with your suggestion I realice that i don't use strings only :), i use ints and floats also. How can i make: if x is iterable (i mean, list, tuples, etc): do something, elif x is not iterable (i mean, strings, ints, floats, etc): do other thing? – Ender Look Apr 02 '17 at 02:51
  • 1
    I would still likely do that same thing. First you have to special-case strings (because strings are iterable, but you don't want to do that). Then you check if it IS iterable by using a for loop inside a try. The third step using `str(variable)` in the except will take care of ints, floats, etc. I'll edit my answer to have an example. – DimeCadmium Apr 02 '17 at 22:32
1

Usually we prefer, isinstance(a, list) because it allows a to be either a list or list subclass.

For better speed, an exact check can to an identity test, type(a) is list. This is a bit faster than using ==.

That said, the norm in Python is to avoid type checks altogether and instead do "duck typing". You call list methods on a and if they succeed, then we deem a to be sufficiently list like.

Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485