1918

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.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Dan
  • 33,953
  • 24
  • 61
  • 87

12 Answers12

2494

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__
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
sykora
  • 96,888
  • 11
  • 64
  • 71
  • 49
    Amazingly simple. Wonder why `dir(x.__class__)` does not list it? – cfi Jan 21 '13 at 10:40
  • 52
    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. – jpmc26 Mar 07 '13 at 20:41
  • 26
    You have to use ````__class__```` directly to be compatible with old-style classes, since their type is just ````instance````. – Quantum7 Aug 07 '13 at 19:50
  • 1
    Since I'm using this is in a `__getattr__` method, if I seek any attributes on `self`, I get a recursion error. Using `type` was of utmost importance in that situation. – Bobort Mar 29 '18 at 18:05
  • 25
    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. – Erik Aronesty Apr 18 '18 at 13:19
  • 8
    @ErikAronesty, `def typename(x): return type(x).__name__` – sleblanc Aug 12 '18 at 22:07
  • 1
    So, I have tried both these solutions on a case where they do not perform as I would expect or wish. ``RandomOverSampler`` from the ``imblearn`` package is a class deriving from a series of parents where one of which is defined as ``SamplerMixin(BaseEstimator, metaclass=ABCMeta)``. In this case, both of the proposed methods return ``ABCMeta`` on an instance of ``RandomOverSampler`` (or the analogous ``RandomUnderSampler`` class) while I was looking for a convenient way to distinguish between these objects at runtime. Any idea on how to get the *actual* class name? – inVader Jan 21 '20 at 15:49
  • @jpmc26 [They can be different](https://stackoverflow.com/a/10633356/4518341). – wjandrea Jun 30 '20 at 00:55
  • 1
    @Bobort Couldn't you just use `super().__getattr__(self, '__class__')`? – wjandrea Jun 30 '20 at 00:58
  • @Bobort I remember reading somewhere that, for efficiency, dunder attributes don't work with custom `__getattr__`, so you wouldn't get a recursion error. Not sure tho. – Roy Cohen Jan 31 '22 at 13:58
529

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

instance.__class__.__name__
mthurlin
  • 26,247
  • 4
  • 39
  • 46
  • 9
    Or instance.__class__ to get the class object :D – Pencilcheck May 28 '13 at 11:15
  • 9
    Is it safe to use double underscore properties? – Eduard Luca Sep 05 '14 at 11:11
  • 7
    @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 –  Jul 10 '15 at 20:48
  • 3
    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. – Eduard Luca Jul 13 '15 at 09:07
  • 46
    @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__). – Leagsaidh Gordon Aug 10 '15 at 22:33
  • 2
    Or if you doing this from inside the class this will work `self.__class__.__name__` – Bostone Nov 26 '19 at 17:49
  • A shorter solution is `type(instance).__name__`. – OrrinPants Mar 08 '23 at 15:26
  • This is what I needed for a utility to create a logger for classes without having a string literal. – user3481644 Mar 16 '23 at 14:25
175

type() ?

>>> class A:
...     def whoami(self):
...         print(type(self).__name__)
...
>>>
>>> class B(A):
...     pass
...
>>>
>>>
>>> o = B()
>>> o.whoami()
'B'
>>>
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
GHZ
  • 3,365
  • 4
  • 24
  • 28
  • 12
    I like this one. This way, it is possible in a base class to get the name of the subclass. – joctee Jun 04 '12 at 11:43
  • 15
    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? – andreb Aug 20 '12 at 21:47
  • 3
    If you're using `type(item)` on a list item the result will be `` while `item.__class__.__name__` holds the class name. – Grochni Aug 06 '14 at 09:43
  • 1
    I think the issue that @Grochni mentions is only relevant for certain classes in Python 2.x, see here: http://stackoverflow.com/questions/6666856/why-does-typemyfield-return-type-instance-and-not-type-field – Nate C-K Feb 22 '15 at 18:09
  • @andreb The original solution is shorter. – OrrinPants Mar 08 '23 at 15:27
51
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.

Jonathan
  • 519
  • 4
  • 2
30

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'
>>>
wjandrea
  • 28,235
  • 9
  • 60
  • 81
Prasath
  • 595
  • 5
  • 11
  • 6
    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. – alcalde Sep 19 '13 at 03:56
23

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'
Yurii Rabeshko
  • 591
  • 8
  • 17
16

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
RyanN
  • 740
  • 8
  • 20
15

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.

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
11

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

Lalit Vavdara
  • 406
  • 4
  • 9
7

To get instance classname:

type(instance).__name__

or

instance.__class__.__name__

both are the same

v.babak
  • 818
  • 11
  • 13
  • [Actually they can be different](https://stackoverflow.com/q/1060499/4518341) if the class overrides `__class__`, or in old style classes (which are obsolete) – wjandrea Jun 30 '20 at 01:07
1

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
Supergamer
  • 411
  • 4
  • 13
0

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))
Yaakov Bressler
  • 9,056
  • 2
  • 45
  • 69