97

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
  • 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. Commented Aug 17, 2011 at 2: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 :) Commented Aug 17, 2011 at 20:37

7 Answers 7

203
isinstance(obj, tuple)
isinstance(obj, basestring)
isinstance(obj, int)
Sign up to request clarification or add additional context in comments.

1 Comment

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!
45

You just use:

type(varname)

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

2 Comments

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
@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).
32

make use of isinstance ?

if isinstance(var, int):

if isinstance(var, str):

if isinstance(var, tuple):

3 Comments

Testing for str will fail on unicode strings. Also, isinstance(var, tuple) will miss any variables that happen to be lists, 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.
In Python 3 you can use a sequence of types to test: isinstance(var, (tuple, list))
Funny that the other guy gets all the upvotes, though you answered first.
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:

4 Comments

You should really use isinstance instead. type() is dangerous when it comes to inheritance.
@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.
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, Despite, in my opinion, replacing 'is' with '==' is not different methodology, I don't mind at all.
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.

1 Comment

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.
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.

2 Comments

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?
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 <mymodule.A instance at 0x123456> by default, but some classes overwrite this description string.
-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.

15 Comments

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 In my answer I was attempting to say if you removed the " double quotes it will work.
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 I've reworded the answer and explained why == is important to people like me. Is it OK now?
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.
|