¿Obtener el nombre de la clase de una instancia?


1437

¿Cómo puedo encontrar un nombre de clase que haya creado una instancia de un objeto en Python si la función de la que estoy haciendo esto es la clase base de la cual se deriva 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 sin analizar el __class__miembro, no estoy seguro de cómo obtener esta información.


¿Qué es exactamente "análisis" de la variable de clase ?
sykora

1
el nombre de nivel superior de la clase a la que pertenece la instancia (sin el nombre del módulo, etc.)
Dan

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

Respuestas:


1910

¿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 usa Python 2, tenga en cuenta que el método anterior funciona solo 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__

41
Increíblemente simple ¿Me pregunto por qué dir(x.__class__)no lo enumera?
cfi

43
¿Por qué usar __class__sobre el typemétodo? De este modo: type(x).__name__. ¿No se desaconseja llamar a los miembros de doble subrayado directamente? Sin __name__embargo, no puedo ver una forma de evitarlo.
jpmc26

25
Debe usar __class__directamente para ser compatible con las clases de estilo antiguo, ya que su tipo es justo instance.
Quantum7

14
Esto se usa con suficiente frecuencia en el registro, el código de orm y el marco de trabajo para que realmente haya un nombre de tipo incorporado (x) ... que requiere que un usuario mire las "tripas" para obtener un nombre no es terriblemente pitónico, IMO.
Erik Aronesty

55
@ErikAronesty,def typename(x): return type(x).__name__
sleblanc

392

¿Quieres el nombre de la clase como una cadena?

instance.__class__.__name__

66
O instancia .__ class__ para obtener el objeto de clase: D
Pencilcheck

8
¿Es seguro usar propiedades de subrayado doble?
Eduard Luca

55
@EduardLuca ¿por qué no sería seguro? Las propiedades incorporadas usan guiones bajos para que no causen ningún conflicto con el código que usted escribe
JC Rocamonde

3
Bueno, sé que los guiones bajos simples significan / sugieren que el método / propiedad debería 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

28
@EduardLuca Los guiones bajos dobles al inicio solo son similares a un guión bajo al inicio, 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

101

tipo() ?

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

esta es la misma que la clase de miembro, pero tengo que analizar este resultado con la mano, que es un poco molesto ...
Dan

8
Me gusta este. De esta manera, es posible en una clase base obtener el nombre de la subclase.
joctee

66
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

2
Si está utilizando type(item)un elemento de la lista, el resultado será <type 'instance'>mientras item.__class__.__name__contenga el nombre de la clase.
Grochni

1
Creo que el problema que menciona @Grochni solo es relevante para ciertas clases en Python 2.x, consulte aquí: stackoverflow.com/questions/6666856/…
Nate CK

43
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 del 'A'que se produce si __name__se invoca el atributo. Simplemente pasando el resultado de A.__class__al strconstructor, el análisis se maneja por usted. Sin embargo, también podría 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 definido en módulos separados.

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


Probado en 2.6.6. Aún funciona bien.
Hamlett

29
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'
>>>

55
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

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

13

Alternativamente, puede usar 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'

10

Además de obtener el __name__atributo especial , es posible que necesite el nombre calificado para una clase / función determinada. Esto se hace agarrando 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'

Como la introspección es lo que buscas, esto siempre es lo que querrás considerar.


2
__qualname__Cabe señalar que es para Python 3.3+
FireAphis

10
Y evitaría nombrar cualquier cosa en mi software "metanfetamina".
Bobort

Explicación relacionada para __qualname__vs __name__: stackoverflow.com/questions/58108488/what-is-qualname-in-python
ti7

0

Para obtener el nombre de clase de instancia:

type(instance).__name__

o

instance.__class__.__name__

ambos son iguales

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.