Ottenere il nome della classe di un'istanza?


1437

Come faccio a scoprire un nome di classe che ha creato un'istanza di un oggetto in Python se la funzione da cui sto eseguendo è la classe di base da cui è derivata la classe dell'istanza?

Pensavo che forse il modulo Inspect mi avrebbe aiutato qui, ma non sembra darmi quello che voglio. E a parte analizzare il __class__membro, non sono sicuro di come ottenere queste informazioni.


Cosa stai "analizzando" esattamente dalla variabile di classe ?
Sykora,

1
il nome di primo livello della classe a cui appartiene l'istanza (senza nome del modulo, ecc ...)
Dan

Penso che il contrario sarebbe molto più difficile (per ottenere la classe in cui è definito il metodo / funzione).
Alexey,

Risposte:


1909

Hai provato l' __name__attributo della classe? cioè type(x).__name__ti darò il nome della classe, che penso sia quello che vuoi.

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

Se stai ancora usando Python 2, nota che il metodo sopra funziona solo con le classi di nuovo stile (in Python 3+ tutte le classi sono classi di "nuovo stile"). Il codice potrebbe utilizzare alcune classi di vecchio stile. Quanto segue funziona per entrambi:

x.__class__.__name__

41
Incredibilmente semplice. Mi chiedo perché dir(x.__class__)non lo elenca?
cfi,

43
Perché usare __class__oltre il typemetodo? In questo modo: type(x).__name__. Chiamare i membri con doppio trattino basso non è direttamente scoraggiato? __name__Tuttavia, non riesco a vedere un modo per aggirare .
jpmc26

25
Devi utilizzare __class__direttamente per essere compatibile con le classi di vecchio stile, poiché il loro tipo è giusto instance.
Quantum7

14
Questo è usato abbastanza spesso nella registrazione, nel codice e nel codice del framework che dovrebbe esserci davvero un typename incorporato (x) ... che richiede a un utente di guardare "budella" per ottenere un nome non terribilmente pitonico, IMO.
Erik Aronesty,

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

391

Vuoi il nome della classe come stringa?

instance.__class__.__name__

6
O istanza .__ class__ per ottenere l'oggetto di classe: D
Pencilcheck,

8
È sicuro utilizzare le proprietà di sottolineatura doppia?
Eduard Luca,

5
@EduardLuca perché non dovrebbe essere sicuro? Le proprietà integrate utilizzano i trattini
bassi in

3
Bene, so che i singoli trattini bassi significano / suggeriscono che il metodo / proprietà dovrebbe essere privato (anche se non puoi davvero implementare metodi privati ​​in Python AFAIK), e mi chiedevo se non fosse così anche con (alcuni) caratteri di sottolineatura doppi.
Eduard Luca,

28
@EduardLuca I caratteri di sottolineatura doppi solo all'inizio sono simili a un singolo carattere di sottolineatura all'inizio, ma anche più "privati" (cerca "mangling di nome di pitone"). I trattini bassi all'inizio e alla fine sono diversi: quelli riservati a Python e non sono privati ​​(ad es. Metodi magici come __init__ e __add__).
Leagsaidh Gordon,

101

genere() ?

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

questo è lo stesso del membro della classe , ma devo analizzare questo risultato a mano, il che è un po 'fastidioso ...
Dan

8
Mi piace questa. In questo modo, è possibile in una classe base ottenere il nome della sottoclasse.
giovedì

6
o self.__class__.__name__invece di type(self).__name__ottenere lo stesso comportamento. A meno che non ci sia qualcosa della type()funzione di cui non sono a conoscenza?
andreb,

2
Se stai usando type(item)una voce di elenco, il risultato sarà <type 'instance'>mentre item.__class__.__name__contiene il nome della classe.
Grochni,

1
Penso che il problema menzionato da @Grochni sia rilevante solo per alcune classi in Python 2.x, vedi qui: stackoverflow.com/questions/6666856/…
Nate CK

43
class A:
  pass

a = A()
str(a.__class__)

Il codice di esempio sopra (quando inserito nell'interprete interattivo) produrrà '__main__.A'al contrario del 'A'quale viene prodotto se l' __name__attributo viene invocato. Passando semplicemente il risultato A.__class__al strcostruttore, l'analisi viene gestita per te. Tuttavia, puoi anche utilizzare il seguente codice se desideri qualcosa di più esplicito.

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

Questo comportamento può essere preferibile se si hanno classi con lo stesso nome definito in moduli separati.

Il codice di esempio fornito sopra è stato testato in Python 2.7.5.


Testato in 2.6.6. Funziona ancora bene.
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):
  ...

Esempio:

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

5
Questo vale solo per il vecchio Python 2.x. In 3.x, bclass () si risolverebbe in bclass (oggetto). E anche allora, nuove classi sono apparse in Python 2.2.
alcalde,

16

Buona domanda.

Ecco un semplice esempio basato su GHZ che potrebbe aiutare qualcuno:

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

In alternativa puoi usare il classmethoddecoratore:

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

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

Utilizzo :

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

10

Oltre a __name__prendere l' attributo speciale , potresti trovare il bisogno del nome qualificato per una determinata classe / funzione. Questo viene fatto afferrando i tipi __qualname__.

Nella maggior parte dei casi, questi saranno esattamente gli stessi, ma, quando si hanno a che fare con classi / metodi nidificati, differiscono nell'output che si ottiene. Per esempio:

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'

Poiché l'introspezione è ciò che stai cercando, questo è sempre ciò che potresti voler considerare.


2
Va notato che __qualname__è per Python 3.3+
FireAphis

10
E eviterei di nominare qualsiasi cosa nel mio software "meth".
Bobort,

Spiegazione correlati per __qualname__vs __name__: stackoverflow.com/questions/58108488/what-is-qualname-in-python
ti7

0

Per ottenere l'istanza classname:

type(instance).__name__

o

instance.__class__.__name__

entrambi sono uguali

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.