Pregunta

Cuál es la diferencia entre type(obj) y obj.__class__?¿Existe alguna vez la posibilidad de type(obj) is not obj.__class__?

Quiero escribir una función que funcione genéricamente en los objetos proporcionados, usando un valor predeterminado de 1 en el mismo tipo que otro parámetro.¿Qué variación, la número 1 o la número 2 a continuación, hará lo correcto?

def f(a, b=None):
  if b is None:
    b = type(a)(1) # #1
    b = a.__class__(1) # #2
¿Fue útil?

Solución

type(obj) y type.__class__ No te comportes 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

Otros consejos

Esta es una vieja pregunta, pero ninguna de las respuestas parece mencionarla.en el caso general, es ES Es posible que una clase de nuevo estilo tenga valores diferentes para type(instance) y 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()

Producción:

<class '__main__.ClassB'>
<class '__main__.ClassA'>
ClassB

La razón es que ClassB está anulando el __class__ descriptor, sin embargo, el campo de tipo interno en el objeto no cambia. type(instance) lee directamente desde ese campo de tipo, por lo que devuelve el valor correcto, mientras que instance.__class__ se 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 al viejo estilo 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 ahora tienen un estilo nuevo ;-).

En Python 2, una clase tiene un estilo nuevo sólo si hereda de otra clase de estilo nuevo (incluyendo object y los distintos tipos incorporados, como dict, list, set, ...) o establece implícita o explícitamente __metaclass__ a type.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top