¿Obteniendo el nombre de clase de una instancia?

1694

¿Cómo averiguo el nombre de la clase que creó una instancia de un objeto en Python si la función desde la que estoy haciendo esto es la clase base de la cual se derivó la clase de la instancia?

Estaba pensando que tal vez el módulo de inspección podría haberme ayudado aquí, pero no parece darme lo que quiero. Y aparte de analizar el __class__miembro, no estoy seguro de cómo obtener esta información.

3
  • ¿Qué está 'analizando' exactamente de la variable de clase ? sykora 4 de febrero de 2009 a las 11:49
  • 1
    el nombre de nivel superior de la clase a la que pertenece la instancia (sin nombre de módulo, etc.)Dan 4 feb 09 a las 11:50
  • Creo que lo contrario sería mucho más difícil (obtener la clase en la que se define el método / función). Alexey 24 feb 2018 a las 8:54
2244

¿Has probado el __name__atributo de la clase? es decir, type(x).__name__te daré el nombre de la clase, que creo que es lo que quieres.

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

Si todavía está usando Python 2, tenga en cuenta que el método anterior solo funciona con clases de estilo nuevo (en Python 3+ todas las clases son clases de "estilo nuevo"). Su código puede usar algunas clases de estilo antiguo. Lo siguiente funciona para ambos:

x.__class__.__name__
9
  • 46
    Increíblemente simple. ¿Me pregunto por qué dir(x.__class__)no lo enumera? cfi 21 de enero de 2013 a las 10:40
  • 46
    ¿Por qué usar __class__sobre el typemétodo? De este modo: type(x).__name__. ¿No se desalienta directamente llamar a los miembros con doble subrayado? Sin __name__embargo, no veo la manera de evitar el uso . jpmc26 7/0313 a las 20:41
  • 26
    Tienes que usarlo __class__directamente para ser compatible con las clases de estilo antiguo, ya que su tipo es just instance. Quantum7 7/0813 a las 19:50
  • 18
    Esto se usa con suficiente frecuencia en el código de registro, orm y marco que realmente debería haber un nombre de tipo incorporado (x) ... requerir que un usuario mire las "agallas" para obtener un nombre no es terriblemente pitónico, en mi opinión. Erik Aronesty 18/04/18 a las 13:19
  • 7
    @ErikAronesty,def typename(x): return type(x).__name__sleblanc 12/08/18 a las 22:07
470

¿Quieres el nombre de la clase como una cadena?

instance.__class__.__name__
6
  • 7
    O instancia .__ class__ para obtener el objeto de clase: DPencilcheck 28 de mayo de 2013 a las 11:15
  • 8
    ¿Es seguro utilizar propiedades de subrayado doble? Eduard Luca 5 de septiembre de 2014 a las 11:11
  • 5
    @EduardLuca ¿por qué no sería seguro? Las propiedades integradas usan guiones bajos para que no causen ningún conflicto con el código que escribeuser4396006 10/07/2015 a las 20:48
  • 3
    Bueno, sé que los guiones bajos simples significan / sugieren que el método / propiedad debe ser privado (aunque realmente no se pueden implementar métodos privados en Python AFAIK), y me preguntaba si ese no es el caso con (algunos) guiones bajos dobles también. Eduard Luca 13/07/2015 a las 9:07
  • 38
    @EduardLuca Los guiones bajos dobles al principio solo son similares a un guión bajo simple al principio, pero aún más "privados" (busque "alteración del nombre de Python"). Los guiones bajos dobles al principio y al final son diferentes: están reservados para Python y no son privados (por ejemplo, métodos mágicos como __init__ y __add__). Leagsaidh Gordon 10/08/15 a las 22:33
126

type() ?

>>> class A:
...     def whoami(self):
...         print(type(self).__name__)
...
>>>
>>> class B(A):
...     pass
...
>>>
>>>
>>> o = B()
>>> o.whoami()
'B'
>>>
5
  • 1
    esto es lo mismo que el miembro de la clase , pero tengo que analizar este resultado a mano, lo cual es un poco molesto ...Dan 4 feb 09 a las 11:47
  • 8
    Me gusta este. De esta forma, es posible en una clase base obtener el nombre de la subclase. joctee 4/06/12 a las 11:43
  • 8
    o en self.__class__.__name__lugar de type(self).__name__tener el mismo comportamiento. ¿A menos que haya algo type()que haga la función que yo no sepa? andreb 20/08/12 a las 21:47
  • 3
    Si está utilizando type(item)en un elemento de la lista, el resultado será <type 'instance'>mientras item.__class__.__name__contiene el nombre de la clase. Grochni 6 de agosto de 2014 a las 9:43
  • 1
    Creo que el problema que menciona @Grochni solo es relevante para ciertas clases en Python 2.x, vea aquí: stackoverflow.com/questions/6666856/…Nate C-K 22/02/15 a las 18:09
46
class A:
  pass

a = A()
str(a.__class__)

El código de muestra anterior (cuando se ingresa en el intérprete interactivo) producirá '__main__.A'en lugar de lo 'A'que se produce si __name__se invoca el atributo. Simplemente pasando el resultado de A.__class__al strconstructor, el análisis se gestiona automáticamente. Sin embargo, también puede usar el siguiente código si desea algo más explícito.

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

Este comportamiento puede ser preferible si tiene clases con el mismo nombre definidas en módulos separados.

El código de muestra proporcionado anteriormente se probó en Python 2.7.5.

0
28

En 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):
  ...

Ejemplo:

>>> 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'
>>>
1
  • 6
    Esto solo es válido para el antiguo Python 2.x. En 3.x, bclass () se resolvería en bclass (objeto). E incluso entonces, aparecieron nuevas clases en Python 2.2. alcalde 19 de septiembre de 2013 a las 3:56
18

Alternativamente, puede utilizar el classmethoddecorador:

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

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

Uso :

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

Buena pregunta.

Aquí hay un ejemplo simple basado en GHZ que podría ayudar a alguien:

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

Además de tomar el __name__atributo especial , es posible que necesite el nombre calificado para una clase / función determinada. Esto se hace tomando los tipos __qualname__.

En la mayoría de los casos, estos serán exactamente los mismos, pero, cuando se trata de clases / métodos anidados, estos difieren en el resultado que obtiene. Por ejemplo:

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'

Dado que lo que buscas es la introspección, esto es lo que siempre debes considerar.

3
4

Simplemente puede usar lo __qualname__que significa el nombre calificado de una función o clase

Ejemplo:

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

enlace de documentación qualname

1
  • esto da el nombre de una clase, no el nombre de clase de una instanciapascal sautot 21 de ene a las 17:54
1

Para obtener el nombre de clase de la instancia:

type(instance).__name__

o

instance.__class__.__name__

ambos son iguales

1