Getting the class name of an instance

Asked 2023-09-21 08:08:02 View 806,914

How do I find out the name of the class used to create an instance of an object in Python?

I'm not sure if I should use the inspect module or parse the __class__ attribute.

  • What exactly are you 'parsing' from the class variable? - anyone
  • the top-level name of the class that the instance belongs to (without module name, etc...) - anyone

Answers

Have you tried the __name__ attribute of the class? ie type(x).__name__ will give you the name of the class, which I think is what you want.

>>> import itertools
>>> x = itertools.count(0)
>>> type(x).__name__
'count'

If you're still using Python 2, note that the above method works with new-style classes only (in Python 3+ all classes are "new-style" classes). Your code might use some old-style classes. The following works for both:

x.__class__.__name__

Answered   2023-09-21 08:08:02

  • Amazingly simple. Wonder why dir(x.__class__) does not list it? - anyone
  • Why use __class__ over the type method? Like so: type(x).__name__. Isn't calling double underscore members directly discouraged? I can't see a way around using __name__, though. - anyone
  • You have to use __class__ directly to be compatible with old-style classes, since their type is just instance. - anyone
  • This is used often enough in logging, orm and framework code that there really should be a builtin typename(x) ... requiring a user to look at the "guts" to get a name isn't terribly pythonic, IMO. - anyone
  • @ErikAronesty, def typename(x): return type(x).__name__ - anyone

Do you want the name of the class as a string?

instance.__class__.__name__

Answered   2023-09-21 08:08:02

  • Or instance.__class__ to get the class object :D - anyone
  • Is it safe to use double underscore properties? - anyone
  • @EduardLuca why wouldn't it be safe? Built-in properties use underscores so that they do not cause any conflict with the code you write - anyone
  • Well I know that single underscores mean / suggest that the method / property should be private (although you can't really implement private methods in Python AFAIK), and I was wondering if that's not the case with (some) double underscores too. - anyone
  • @EduardLuca Double underscores at the start only are similar to a single underscore at the start, but even more "private" (look up "python name mangling"). Double underscores at beginning and end are different - those are reserved for python and are not private (e.g. magic methods like __init__ and __add__). - anyone

type() ?

>>> class A:
...     def whoami(self):
...         print(type(self).__name__)
...
>>>
>>> class B(A):
...     pass
...
>>>
>>>
>>> o = B()
>>> o.whoami()
'B'
>>>

Answered   2023-09-21 08:08:02

  • I like this one. This way, it is possible in a base class to get the name of the subclass. - anyone
  • or self.__class__.__name__ instead of type(self).__name__ to get the same behaviour. Unless there is something the type() function does that I am not aware of? - anyone
  • If you're using type(item) on a list item the result will be <type 'instance'> while item.__class__.__name__ holds the class name. - anyone
  • I think the issue that @Grochni mentions is only relevant for certain classes in Python 2.x, see here: stackoverflow.com/questions/6666856/… - anyone
  • @andreb The original solution is shorter. - anyone
class A:
  pass

a = A()
str(a.__class__)

The sample code above (when input in the interactive interpreter) will produce '__main__.A' as opposed to 'A' which is produced if the __name__ attribute is invoked. By simply passing the result of A.__class__ to the str constructor the parsing is handled for you. However, you could also use the following code if you want something more explicit.

"{0}.{1}".format(a.__class__.__module__,a.__class__.__name__)

This behavior can be preferable if you have classes with the same name defined in separate modules.

The sample code provided above was tested in Python 2.7.5.

Answered   2023-09-21 08:08:02

In Python 2,

type(instance).__name__ != instance.__class__.__name__
# if class A is defined like
class A():
   ...

type(instance) == instance.__class__
# if class A is defined like
class A(object):
  ...

Example:

>>> class aclass(object):
...   pass
...
>>> a = aclass()
>>> type(a)
<class '__main__.aclass'>
>>> a.__class__
<class '__main__.aclass'>
>>>
>>> type(a).__name__
'aclass'
>>>
>>> a.__class__.__name__
'aclass'
>>>


>>> class bclass():
...   pass
...
>>> b = bclass()
>>>
>>> type(b)
<type 'instance'>
>>> b.__class__
<class __main__.bclass at 0xb765047c>
>>> type(b).__name__
'instance'
>>>
>>> b.__class__.__name__
'bclass'
>>>

Answered   2023-09-21 08:08:02

  • This only holds true for old Python 2.x. In 3.x, bclass() would resolve to bclass(object). And even then, new classes appeared in Python 2.2. - anyone

Alternatively you can use the classmethod decorator:

class A:
    @classmethod
    def get_classname(cls):
        return cls.__name__

    def use_classname(self):
        return self.get_classname()

Usage:

>>> A.get_classname()
'A'
>>> a = A()
>>> a.get_classname()
'A'
>>> a.use_classname()
'A'

Answered   2023-09-21 08:08:02

Good question.

Here's a simple example based on GHZ's which might help someone:

>>> class person(object):
        def init(self,name):
            self.name=name
        def info(self)
            print "My name is {0}, I am a {1}".format(self.name,self.__class__.__name__)
>>> bob = person(name='Robert')
>>> bob.info()
My name is Robert, I am a person

Answered   2023-09-21 08:08:02

Apart from grabbing the special __name__ attribute, you might find yourself in need of the qualified name for a given class/function. This is done by grabbing the types __qualname__.

In most cases, these will be exactly the same, but, when dealing with nested classes/methods these differ in the output you get. For example:

class Spam:
    def meth(self):
        pass
    class Bar:
        pass

>>> s = Spam()
>>> type(s).__name__ 
'Spam'
>>> type(s).__qualname__
'Spam'
>>> type(s).Bar.__name__       # type not needed here
'Bar'
>>> type(s).Bar.__qualname__   # type not needed here 
'Spam.Bar'
>>> type(s).meth.__name__
'meth'
>>> type(s).meth.__qualname__
'Spam.meth'

Since introspection is what you're after, this is always you might want to consider.

Answered   2023-09-21 08:08:02

You can simply use __qualname__ which stands for qualified name of a function or class

Example:

>>> class C:
...     class D:
...         def meth(self):
...             pass
...
>>> C.__qualname__
'C'
>>> C.D.__qualname__
'C.D'
>>> C.D.meth.__qualname__
'C.D.meth'

documentation link qualname

Answered   2023-09-21 08:08:02

  • this gives the name of a class not the class name of an instance - anyone
  • This was already suggested by @Dimitris in 2017 - anyone

To get instance classname:

type(instance).__name__

or

instance.__class__.__name__

both are the same

Answered   2023-09-21 08:08:02

You can first use type and then str to extract class name from it.

class foo:pass;

bar:foo=foo();
print(str(type(bar))[8:-2][len(str(type(bar).__module__))+1:]);

Result

foo

Answered   2023-09-21 08:08:02

  • That's hard to read, are those inline methods I don't know about? - anyone
  • If I came across a line such as this, I'd definitely "annotate" the code just to know the name of whom I was going to swear a lot. - anyone

If you're looking to solve this for a list (or iterable collection) of objects, here's how I would solve:

from operator import attrgetter

# Will use a few data types to show a point
my_list = [1, "2", 3.0, [4], object(), type, None]

# I specifically want to create a generator
my_class_names = list(map(attrgetter("__name__"), map(type, my_list))))

# Result:
['int', 'str', 'float', 'list', 'object', 'type', 'NoneType']


# Alternatively, use a lambda
my_class_names = list(map(lambda x: type(x).__name__, my_list))

Answered   2023-09-21 08:08:02