python new-style-class

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