Variable type detection in python

244 views Asked by At

I am looking at methods for detecting the type of a variable (list vs string) within python (2.5+), and came across some other answers which seemed overly convoluted.

I have found one can do

x.__class__.__name__

to get a string containing the class name. What, if anything, is wrong with this? Is it not portable? When would it fail?

4

There are 4 answers

1
shx2 On BEST ANSWER

The problem is that different classes can have the same name.

The straightforward example is for classes defined in different modules (e.g. think of generic common names such as Node or Connection).

However, it's easy to demonstrate this problem even in a single module:

class A(object): pass
B = A
class A(object): pass
C = A

b = B()
c = C()
b.__class__.__name__ == c.__class__.__name__
=> True
type(b) == type(c)
=> False

If you don't have to have string-representation of the class, simply use the type object returned by calling type(obj).

Of course, depending on what you use it for, it might be best to use isinstance instead of dealing with type objects directly.

0
Martijn Pieters On

It'll fail for old-style classes; isinstance() works just fine:

>>> class OldStyle: pass
...
>>> OldStyle.__class__.__name__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: class OldStyle has no attribute '__class__'
>>> isinstance(OldStyle(), OldStyle)
True

Note that it is better to use isinstance() and accept subclasses, including virtual subclasses (via abstract base classes). Don't tie your code to a specific type.

For example, you'd not want to test for obj.__class__.__name__ in ('int', 'float', 'complex') when you could just use isinstance(obj, numbers.Number); that way your code will accept decimal.Decimal objects too.

0
Łukasz Rogalski On

One common pitfails for detecting strings in Python 2.x would be mixing up str and unicode types.

assert isinstance("", str) is True
assert isinstance(u"", str) is True  # AssertionError!
assert isinstance(u"", unicode) is True
assert isinstance(u"", unicode) is True
assert isinstance("", unicode) is True  # AssertionError!
# Both lines below are always correct
assert isinstance("", basestring) is True
assert isinstance(u"", basestring) is True

As you can see, all string derives from same base class - that's what allow uniform type check. It won't be possible with class name string look up.

>>> "".__class__.__name__
'str'
>>> u"".__class__.__name__
'unicode'
0
AudioBubble On

You’re not really supposed to call magic functions, you could just use type() or isinstance(). The main difference between the two is that isinstance() supports inheritance, so if your classes inherit from other classes you might wanna use isinstance().