Den Klassennamen einer Instanz erhalten?

1437

Wie finde ich einen Klassennamen heraus, der eine Instanz eines Objekts in Python erstellt hat, wenn die Funktion, von der ich dies mache, die Basisklasse ist, von der die Klasse der Instanz abgeleitet wurde?

Ich dachte, vielleicht hat mir das Inspektionsmodul hier geholfen, aber es scheint mir nicht das zu geben, was ich will. Und kurz bevor __class__ich das Mitglied analysiere , bin ich mir nicht sicher, wie ich an diese Informationen kommen soll.

Dan
quelle
Was genau "analysieren" Sie aus der Klassenvariablen ?
Sykora
1
Der Name der obersten Ebene der Klasse, zu der die Instanz gehört (ohne Modulname usw.)
Dan
Ich denke, das Gegenteil wäre viel schwieriger (um die Klasse zu erhalten, in der die Methode / Funktion definiert ist).
Alexey

Antworten:

1908

Haben Sie das __name__Attribut der Klasse ausprobiert ? dh type(x).__name__geben Sie den Namen der Klasse, die ich denke, ist, was Sie wollen.

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

Wenn Sie immer noch Python 2 verwenden, beachten Sie, dass die obige Methode nur mit Klassen neuen Stils funktioniert (in Python 3+ sind alle Klassen Klassen neuen Stils). Ihr Code verwendet möglicherweise einige Klassen alten Stils. Folgendes funktioniert für beide:

x.__class__.__name__
Sykora
quelle
41
Erstaunlich einfach. Frage mich, warum dir(x.__class__)es nicht auflistet?
cfi
43
Warum __class__über die typeMethode verwenden? Wie so : type(x).__name__. Wird das Anrufen von Mitgliedern mit doppeltem Unterstrich nicht direkt entmutigt? Ich sehe jedoch keinen Weg, um es zu benutzen __name__.
jpmc26
25
Sie müssen __class__direkt verwenden, um mit Klassen alten Stils kompatibel zu sein, da deren Typ gerecht ist instance.
Quantum7
14
Dies wird häufig genug in Protokollierungs-, Orm- und Framework-Code verwendet, sodass es wirklich einen eingebauten Typnamen (x) geben sollte. Ein Benutzer muss sich die "Eingeweide" ansehen, um einen Namen zu erhalten, ist nicht besonders pythonisch, IMO.
Erik Aronesty
5
@ErikAronesty,def typename(x): return type(x).__name__
sleblanc
390

Möchten Sie den Namen der Klasse als Zeichenfolge?

instance.__class__.__name__
Truppo
quelle
6
Oder Instanz .__ class__, um das Klassenobjekt zu erhalten: D
Pencilcheck
8
Ist es sicher, doppelte Unterstricheigenschaften zu verwenden?
Eduard Luca
5
@EduardLuca warum wäre es nicht sicher? Eingebaute Eigenschaften verwenden Unterstriche, damit sie keinen Konflikt mit dem von Ihnen geschriebenen Code verursachen
JC Rocamonde
3
Nun, ich weiß, dass einzelne Unterstriche bedeuten / vorschlagen, dass die Methode / Eigenschaft privat sein sollte (obwohl Sie private Methoden in Python AFAIK nicht wirklich implementieren können), und ich habe mich gefragt, ob dies auch bei (einigen) doppelten Unterstrichen nicht der Fall ist.
Eduard Luca
28
@EduardLuca Doppelte Unterstriche am Anfang ähneln nur einem einzelnen Unterstrich am Anfang, sind jedoch noch "privater" (siehe "Python Name Mangling"). Doppelte Unterstriche am Anfang und am Ende sind unterschiedlich - diese sind für Python reserviert und nicht privat (z. B. magische Methoden wie __init__ und __add__).
Leagsaidh Gordon
101

Art() ?

>>> class A(object):
...    def whoami(self):
...       print type(self).__name__
...
>>>
>>> class B(A):
...    pass
...
>>>
>>>
>>> o = B()
>>> o.whoami()
'B'
>>>
GHZ
quelle
Dies ist das gleiche wie das Klassenmitglied , aber ich muss dieses Ergebnis von Hand analysieren, was ein bisschen nervig ist ...
Dan
8
Ich mag diesen. Auf diese Weise ist es in einer Basisklasse möglich, den Namen der Unterklasse abzurufen.
Joctee
6
oder self.__class__.__name__anstatt type(self).__name__das gleiche Verhalten zu bekommen. Es sei denn, es gibt etwas, dessen type()Funktion mir nicht bekannt ist?
Andreb
2
Wenn Sie type(item)ein Listenelement verwenden, wird das Ergebnis angezeigt, <type 'instance'>solange item.__class__.__name__der Klassenname enthalten ist.
Grochni
1
Ich denke, das Problem, das @Grochni erwähnt, ist nur für bestimmte Klassen in Python 2.x relevant, siehe hier: stackoverflow.com/questions/6666856/…
Nate CK
43
class A:
  pass

a = A()
str(a.__class__)

Der obige Beispielcode (bei Eingabe in den interaktiven Interpreter) erzeugt '__main__.A'im Gegensatz zu 'A'dem, der erzeugt wird, wenn das __name__Attribut aufgerufen wird. Durch einfaches Übergeben des Ergebnisses A.__class__an den strKonstruktor wird die Analyse für Sie durchgeführt. Sie können jedoch auch den folgenden Code verwenden, wenn Sie etwas expliziteres wünschen.

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

Dieses Verhalten kann vorzuziehen sein, wenn Sie Klassen mit demselben Namen in separaten Modulen definiert haben.

Der oben bereitgestellte Beispielcode wurde in Python 2.7.5 getestet.

Jonathan
quelle
Getestet in 2.6.6. Funktioniert immer noch gut.
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):
  ...

Beispiel:

>>> 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'
>>>
Prasath
quelle
5
Dies gilt nur für das alte Python 2.x. In 3.x würde bclass () in bclass (Objekt) aufgelöst. Und selbst dann erschienen in Python 2.2 neue Klassen.
Alcalde
16

Gute Frage.

Hier ist ein einfaches Beispiel basierend auf GHZs, das jemandem helfen könnte:

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

Alternativ können Sie den classmethodDekorateur verwenden:

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

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

Verwendung :

>>> A.get_classname()
'A'
>>> a = A()
>>> a.get_classname()
'A'
>>> a.use_classname()
'A'
Yurii Rabeshko
quelle
10

Abgesehen davon __name__, dass Sie das spezielle Attribut abrufen, benötigen Sie möglicherweise den qualifizierten Namen für eine bestimmte Klasse / Funktion. Dies geschieht durch Ergreifen der Typen __qualname__.

In den meisten Fällen sind diese genau gleich, aber beim Umgang mit verschachtelten Klassen / Methoden unterscheiden sich diese in der Ausgabe, die Sie erhalten. Zum Beispiel:

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'

Da Introspektion das ist, wonach Sie suchen, sollten Sie dies immer in Betracht ziehen.

Dimitris Fasarakis Hilliard
quelle
2
Sollte beachtet werden, dass __qualname__für Python 3.3+
FireAphis
10
Und ich würde es vermeiden, irgendetwas in meiner Software "meth" zu nennen.
Bobort
Verwandte Erklärung für __qualname__vs __name__: stackoverflow.com/questions/58108488/what-is-qualname-in-python
ti7
0

So erhalten Sie den Klassennamen der Instanz:

type(instance).__name__

oder

instance.__class__.__name__

beide sind gleich

v.babak
quelle