90

I am trying to figure out a type mismatch while adding a string to another string in a concatenate operation.

Basically the error returned is a TypeError (cannot concatenate string and tuple); so I would like to figure out where I assigned a value as tuple instead of string.

All the values that I assign are strings, so I gotta figure out where the tuple is coming from, so I was hoping that there is a way in Python to find out what is contained inside a variable and what type is it.

So far using pdb I was able to check the content of the variables, and I get correctly the values that I would expect; but I would like to know also the type of the variable (by logic, if the compiler is able to raise a type error, it means that it knows what is inside a variable and if it is compatible with the operation to perform; so there must be a way to get that value/flag out).

Is there any way to print out the type of a variable in python?

BTW, I tried to change all my variables to be explicitly strings, but is not feasible to force str (myvar), so I cannot just cast as string type everywhere I use strings.

  • 2
    Not wanting to be picky, but variables never have a type in Python, only objects (referenced by variables) do. Because of this there are no real type casts, only object conversion functions. – Jürgen Strobel Aug 17 '11 at 02:17
  • Indeed Jurgen; I am not fully aware of how python works under the hood, but i assume that is an object oriented language, so when i create a variable it will create an object of the right datatype and reference it with a pointer, so when i use the variable i am in fact using an instance of the object string (or whatever other datatype). The end point thou is to get the type of that object :) –  Aug 17 '11 at 20:37

7 Answers7

192
isinstance(obj, tuple)
isinstance(obj, basestring)
isinstance(obj, int)
Nicolae Dascalu
  • 3,425
  • 2
  • 19
  • 17
  • thanks for the reply; this is great for a check while running the program, but I am trying to get the value while debugging with pdb. This is a great way to avoid the problem! –  Aug 17 '11 at 20:31
43

You just use:

type(varname)

which will output int, str, float, etc...

Gabriel Ross
  • 5,168
  • 1
  • 28
  • 30
  • Using `__class__` is almost always better than using `type` because in most situations, they'll return the same thing, except that `type` will declare the type of all old-style classes to be 'instance'. refer to [this SO question](http://stackoverflow.com/questions/1060499/difference-between-typeobj-and-obj-class) – Darren Yin Aug 17 '11 at 01:33
  • @DarrenYin It isn't true that `type(o)` and `o.__class__` **always** return the same thing. Most upvoted answer in linked question says that but it didn't exist when you linked it. Additionally `type` requires less typing and looks like public API function (no underscores). – WloHu May 29 '19 at 08:53
31

make use of isinstance ?

if isinstance(var, int):

if isinstance(var, str):

if isinstance(var, tuple):
Drake Guan
  • 14,514
  • 15
  • 67
  • 94
  • Testing for `str` will fail on `unicode` strings. Also, `isinstance(var, tuple)` will miss any variables that happen to be `list`s, which will often arise in situations such as these. Of course, you might want to error out if the var is an instance of a `list`, but it's good to be sure that you know what's going to happen in different situations. – Darren Yin Aug 17 '11 at 01:30
  • 5
    In Python 3 you can use a sequence of types to test: `isinstance(var, (tuple, list))` – bugmenot123 Jan 23 '18 at 10:40
  • Funny that the other guy gets all the upvotes, though you answered first. – qwerty_so Jul 11 '19 at 18:36
11

Please note, should you wanted to check your var type in if statement, the construct if type(varname) == "tuple": won't work. But these will:

if type(varname) is tuple:
if type(varname) is list:
if type(varname) is dict:
if type(varname) is int:
if type(varname) is str:
Goujon
  • 606
  • 8
  • 16
  • 4
    You should really use isinstance instead. type() is dangerous when it comes to inheritance. – bugmenot123 Jan 23 '18 at 10:41
  • @bugmenot123, I'm not covering all the possible outcomes, I'm making note about the mistake that people usually do when trying to check for type and then got surprised when it's not working. Otherwise, you're absolutely right. – Goujon Jul 04 '18 at 21:07
  • I hope you don't mind but I referenced your answer in my own and countered with a different methodology. If you do mind I will remove the reference. Thanks. – WinEunuuchs2Unix Dec 15 '19 at 22:10
  • @WinEunuuchs2Unix, Despite, in my opinion, replacing 'is' with '==' is not different methodology, I don't mind at all. – Goujon Dec 23 '19 at 13:53
5

You probably want to test (assuming Python 2.x) using isinstance(obj, basestring). You have the options of using isinstance, type, and calling the attribute __class__, but isinstance is likely to be the one you want here. Take a look at this article for a more thorough treatment of the differences between the three options.

Darren Yin
  • 628
  • 3
  • 10
  • Thanks Darren; I will probably do the testing using your suggestion, but at the moment i am using pdb; so I can figure out which one is the problematic var and avoid to do the same mistake (I like defensive coding but at the same time i prefer to avoid to make a mistake in first instance, instead than relying on a check to catch a possible mistake ). Interesting that there is also the __class__ attribute; never heard of it. –  Aug 17 '11 at 20:34
1

repr(object) will give a textual description of object, which should show type and value. Your can print or view this in the debugger.

For simple values repr usually returns the same string as you would write the value literally in code. For custom classes it gives the class name and object id, or something else if the class'es

__repr__

is overridden.

Jürgen Strobel
  • 2,200
  • 18
  • 30
  • Thanks for the reply Jurgen. I tried repr but it returns me the value of the variable *in my case the string), so it does the same that p(varname) does...am I doing something wrong, since I should see as you mentioned, type, value and description of the object? –  Aug 17 '11 at 20:39
  • 1
    No. It returns a string literal for a str or unicode, *including* the quotes, so you should recognize it as that type. It returns unquoted digits for integer types and similiar for other numeric types. For a custom class A, it returns something like by default, but some classes overwrite this description string. – Jürgen Strobel Aug 17 '11 at 21:19
-2

To complement Goujon's answer consider this list of mixed integers and tuples:

for f in fills:
    print (type(f), f)
    if type(f)==int : print "INTEGER!!!"

Generates this output:

(<type 'int'>, 0)
INTEGER!!!
(<type 'tuple'>, (62973, 39058, 25708, 102))
(<type 'int'>, 1)
INTEGER!!!
(<type 'tuple'>, (16968, 12069, 3329, 102))
(<type 'int'>, 2)
INTEGER!!!
(<type 'tuple'>, (24939, 62205, 30062, 102))
(<type 'tuple'>, (32911, 32911, 0, 153))
(<type 'tuple'>, (32911, 0, 0, 153))
(<type 'tuple'>, (32911, 0, 32911, 153))
(<type 'tuple'>, (65535, 0, 0, 153))
(<type 'tuple'>, (0, 0, 65535, 153))
(<type 'tuple'>, (0, 32911, 0, 153))
(<type 'tuple'>, (0, 65535, 65535, 153))

So the secret isn't to test for "int" character string but, rather test for int keyword instead. If you are like me and migrating from the Bash scripting world, using == tests in the Python scripting world will probably be your first step.

WinEunuuchs2Unix
  • 1,801
  • 1
  • 17
  • 34
  • 1
    You have not read Goujon's answer correctly. They specifically wrote, *"the construct if type(varname) == "tuple": won't work"*, and then explained the correct way. – kaya3 Dec 15 '19 at 22:21
  • @kaya3 In my answer I was attempting to say if you removed the `"` double quotes it will work. – WinEunuuchs2Unix Dec 15 '19 at 22:26
  • 2
    I understood what you wrote in your answer; it is wrong, because you are saying Goujon's answer made this mistake, when in fact Goujon's answer *identified that it is a mistake*. Your fix is the same as what Goujon wrote as the solution to that problem. – kaya3 Dec 15 '19 at 22:27
  • @kaya3 I've reworded the answer and explained why `==` is important to people like me. Is it OK now? – WinEunuuchs2Unix Dec 15 '19 at 22:30
  • 1
    Your answer is no longer wrong, but it's not clear what you've added to the existing answer other than that you can use `==` instead of `is` if you want. There is no practical difference except in very rare edge-cases, and in those cases `is` is the correct choice. – kaya3 Dec 15 '19 at 22:32
  • @kaya3 That is all true. By the same token I could use `a=1` and later use `if a is 1:` and do some stuff. But I'm more comfortable with `if a == 1` due to my bash scripting background. The spirit of this answer is to help others like myself making the leap from bash to python. However I will be happy to delete the answer if it adds nothing. – WinEunuuchs2Unix Dec 15 '19 at 22:38
  • Comparing numbers with `is` is not safe; it works for classes like `int` only because there can't be different copies of the class itself. See https://stackoverflow.com/questions/15008380/double-equals-vs-is-in-python – kaya3 Dec 15 '19 at 22:40
  • Python 2 will be deprecated in 2 weeks, how are you still using it? – Boris Verkhovskiy Dec 15 '19 at 22:42
  • @kaya3 So Goujon was saying `type(f) == "int"` doesn't work, I was saying `type(f) == int` does work and you are saying don't use `type(f) == int`. – WinEunuuchs2Unix Dec 15 '19 at 22:44
  • @Boris I'm actually confused what I'm using. I'm on Ubuntu 16.04 and my python header stub checks for `Tkinter` vs `tkinter` and imports accordingly. Ubuntu 16.04 is both python `2.7.12` and python `3.5` it's kind of confusing really. My shebang is `#!/usr/bin/env python` and I let the shell work out the fine details of versions. – WinEunuuchs2Unix Dec 15 '19 at 22:46
  • I'm not saying don't use `type(f) == int`, I'm saying it has no advantages over `type(f) is int`. It has a very nitpicky theoretical disadvantage but that will only happen with code explicitly written to create a bug, so in practice you are safe to do either with `int`. However, you should learn the difference between `==` and `is` to know which one is what you want in each situation. – kaya3 Dec 15 '19 at 22:48
  • There is no need to delete your answer. Just be more careful to read things carefully before saying they are wrong in the future. – kaya3 Dec 15 '19 at 22:55
  • @kaya3 I will probably delete anyway due to down votes. But your point is well taken that they literally didn't say `==` wouldn't work but figuratively said it wouldn't work because other side of equation was double quoted instead of keyword. – WinEunuuchs2Unix Dec 15 '19 at 22:59
  • @WinEunuuchs2Unix on Ubuntu 16.04 `/usr/bin/env python` will almost certainly be `python2`. You need to specify `python3` in the shebang. – Boris Verkhovskiy Dec 15 '19 at 23:02
  • @Boris I have no love for Python `2.7.12` nor Python `3.5` I only care that my code works on everything. I've also dabbled on Windows 10 WSL using VcXsrv and this Christmas I look forward to trying the same Python apps I'm developing on it as well. I might have to expand the `try:` / `except ImportError:` program header stub at that time. Although it's cool that Microsoft adopted "Bash on Windows" recently, it's even cooler to find out "Python on Everything" has been around longer. – WinEunuuchs2Unix Dec 15 '19 at 23:07