Unterschied zwischen Typ (OBJ) und obj .__ class__
-
21-08-2019 - |
Frage
Was ist der Unterschied zwischen type(obj)
und obj.__class__
? Gibt es überhaupt eine Möglichkeit type(obj) is not obj.__class__
?
Ich möchte eine Funktion schreiben, die allgemein auf den gelieferten Objekten arbeitet, einen Standardwert von 1 in der gleichen Art wie ein anderer Parameter verwendet wird. Welche Variante # 1 oder # 2 unten gehen, das Richtige zu tun?
def f(a, b=None):
if b is None:
b = type(a)(1) # #1
b = a.__class__(1) # #2
Lösung
type(obj)
und type.__class__
verhalten sich nicht gleich für alten Stil Klassen:
>>> class a(object):
... pass
...
>>> class b(a):
... pass
...
>>> class c:
... pass
...
>>> ai=a()
>>> bi=b()
>>> ci=c()
>>> type(ai) is ai.__class__
True
>>> type(bi) is bi.__class__
True
>>> type(ci) is ci.__class__
False
Andere Tipps
Dies ist eine alte Frage, aber keine der Antworten scheint, dass zu erwähnen. im allgemeinen Fall, es möglich, dass eine neuen Stil-Klasse unterschiedliche Werte für type(instance)
und instance.__class__
muß:
class ClassA(object):
def display(self):
print("ClassA")
class ClassB(object):
__class__ = ClassA
def display(self):
print("ClassB")
instance = ClassB()
print(type(instance))
print(instance.__class__)
instance.display()
Ausgabe:
<class '__main__.ClassB'>
<class '__main__.ClassA'>
ClassB
Der Grund dafür ist, dass ClassB
den __class__
Descriptor überschreiben, aber das interne Typenfeld in dem Objekt wird nicht verändert. type(instance)
liest unmittelbar von diesem Typ-Feld, so gibt sie den korrekten Wert, während instance.__class__
auf den neuen Deskriptor bezieht sich den ursprünglichen Deskriptor durch Python vorgesehen ersetzt, die das interne Typfeld liest. Statt dass die interne Feld liest, gibt es einen fest codierten Wert.
Old-Style-Klassen sind das Problem, Seufzer:
>>> class old: pass
...
>>> x=old()
>>> type(x)
<type 'instance'>
>>> x.__class__
<class __main__.old at 0x6a150>
>>>
Kein Problem in Python 3, da alle Klassen neue Stile sind jetzt; -).
In Python 2, eine Klasse ist neu Stil nur, wenn es von einer anderen neuen Stil-Klasse erbt (einschließlich object
und der verschiedenen eingebauten Typen wie dict
, list
, set
, ...) oder implizit oder explizit setzt __metaclass__
type
.