Pergunta

O que é a diferença entre type(obj) e obj.__class__? Há sempre uma possibilidade de type(obj) is not obj.__class__?

Eu quero escrever uma função que funciona genericamente sobre os objetos fornecidos, utilizando um valor padrão de 1 no mesmo tipo como outro parâmetro. Cuja variação, # 1 ou # 2 abaixo, vai fazer a coisa certa?

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

Solução

type(obj) e type.__class__ não se comportam da mesma para as classes de estilo antigo:

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

Outras dicas

Esta é uma questão de idade, mas nenhuma das respostas parece mencionar isso. no caso geral, ele é possível para uma classe de estilo novo para ter 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()

Output:

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

A razão é que ClassB está substituindo o descritor __class__, no entanto, o campo de tipo interno no objeto não é alterado. type(instance) lê directamente a partir de que tipo de campo, de modo que devolve o valor correcto, ao passo que instance.__class__ refere-se ao novo descritor substituindo o descritor original fornecido pelo pitão, que lê o campo de tipo interno. Em vez de ler que tipo de campo interno, ele retorna um valor codificado.

aulas de estilo antigo são o problema, suspiro:

>>> class old: pass
... 
>>> x=old()
>>> type(x)
<type 'instance'>
>>> x.__class__
<class __main__.old at 0x6a150>
>>> 

Não é um problema em Python 3 já que todas as classes são novo estilo agora; -).

Em Python 2, uma classe só é novo estilo de se herda de outra classe de estilo novo (incluindo object e os vários tipos internos, como dict, list, set, ...) ou implícita ou explicitamente conjuntos __metaclass__ para type.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top