python - Diferencia entre tipo(obj) y obj.__ clase__
new-style-class (3)
¿Cuál es la diferencia entre type(obj)
y obj.__class__
? ¿Existe alguna posibilidad de que type(obj) is not obj.__class__
?
Quiero escribir una función que funcione genéricamente en los objetos suministrados, utilizando un valor predeterminado de 1 en el mismo tipo que otro parámetro. ¿Qué variación, n. ° 1 o n. ° 2 a continuación, va a hacer lo correcto.
def f(a, b=None):
if b is None:
b = type(a)(1) # #1
b = a.__class__(1) # #2
Esta es una vieja pregunta, pero ninguna de las respuestas parece mencionar eso. en el caso general, ES instance.__class__
una clase de estilo nuevo tenga valores diferentes para type(instance)
e instance.__class__
:
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()
Salida:
<class ''__main__.ClassB''>
<class ''__main__.ClassA''>
ClassB
El motivo es que ClassB
__class__
descriptor __class__
; sin embargo, el campo de tipo interno del objeto no se modifica. type(instance)
lee directamente desde ese campo de tipo, por lo que devuelve el valor correcto, mientras que la instance.__class__
refiere al nuevo descriptor que reemplaza el descriptor original proporcionado por Python, que lee el campo de tipo interno. En lugar de leer ese campo de tipo interno, devuelve un valor codificado.
Las clases de estilo antiguo son el problema, suspiro:
>>> class old: pass
...
>>> x=old()
>>> type(x)
<type ''instance''>
>>> x.__class__
<class __main__.old at 0x6a150>
>>>
No es un problema en Python 3 ya que todas las clases son de estilo nuevo ahora ;-).
En Python 2, una clase es de estilo nuevo solo si hereda de otra clase de estilo nuevo (incluidos el object
y los diversos tipos incorporados, como dict
, list
, set
, ...) o implícita o explícitamente establece __metaclass__
.
type(obj)
y type.__class__
no se comportan igual para las clases de estilo antiguo:
>>> 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