1808

How do I find out a name of class that created an instance of an object in Python if the function I am doing this from is the base class of which the class of the instance has been derived?

Was thinking maybe the inspect module might have helped me out here, but it doesn't seem to give me what I want. And short of parsing the __class__ member, I'm not sure how to get at this information.

martineau
  • 112,593
  • 23
  • 157
  • 280
Dan
  • 32,023
  • 22
  • 57
  • 85

10 Answers10

2363

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
  • 10,733
  • 7
  • 77
  • 79
sykora
  • 89,664
  • 11
  • 61
  • 71
  • 46
    Amazingly simple. Wonder why `dir(x.__class__)` does not list it? – cfi Jan 21 '13 at 10:40
  • 48
    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
  • 21
    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
  • 7
    @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
500

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

instance.__class__.__name__
mthurlin
  • 25,019
  • 4
  • 37
  • 46
  • 9
    Or instance.__class__ to get the class object :D – Pencilcheck May 28 '13 at 11:15
  • 8
    Is it safe to use double underscore properties? – Eduard Luca Sep 05 '14 at 11:11
  • 6
    @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
  • 42
    @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
  • 1
    Or if you doing this from inside the class this will work `self.__class__.__name__` – Bostone Nov 26 '19 at 17:49
153

type() ?

>>> class A:
...     def whoami(self):
...         print(type(self).__name__)
...
>>>
>>> class B(A):
...     pass
...
>>>
>>>
>>> o = B()
>>> o.whoami()
'B'
>>>
Boris Verkhovskiy
  • 10,733
  • 7
  • 77
  • 79
GHZ
  • 3,095
  • 3
  • 23
  • 26
  • 11
    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
  • 11
    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
49
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
  • 499
  • 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
  • 23,210
  • 7
  • 49
  • 68
Prasath
  • 545
  • 4
  • 9
  • 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
19

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
  • 541
  • 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
  • 730
  • 8
  • 19
13

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
  • 136,212
  • 29
  • 242
  • 233
7

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
  • 198
  • 2
  • 8
6

To get instance classname:

type(instance).__name__

or

instance.__class__.__name__

both are the same

v.babak
  • 678
  • 9
  • 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