Domanda

Qual è la differenza tra type(obj) e obj.__class__? C'è sempre la possibilità di type(obj) is not obj.__class__?

Voglio scrivere una funzione che funziona genericamente sugli oggetti in dotazione, utilizzando un valore di default di 1 dello stesso tipo di un altro parametro. Quale variante, # 1 o # 2 qui sotto, sta per fare la cosa giusta?

def f(a, b=None):
  if b is None:
    b = type(a)(1) # #1
    b = a.__class__(1) # #2
È stato utile?

Soluzione

type(obj) e type.__class__ non si comportano lo stesso per le classi vecchio stile:

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

Altri suggerimenti

Questa è una vecchia questione, ma nessuna delle risposte sembra di dire che. nel caso generale, è possibile per una classe di nuovo stile di avere valori diversi per 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

La ragione è che ClassB è sovrascrivendo il __class__ descrittore, tuttavia il campo tipo interno nell'oggetto non viene modificato. <=> legge da tale tipo di campo, quindi restituisce il valore corretto, che <=> riferisce al nuovo descrittore sostituendo il descrittore originale fornito da Python che legge il campo tipo interno. Invece di leggere quel campo tipo interno, restituisce un valore hardcoded.

classi Vecchio stile sono il problema, sospiro:

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

Non è un problema in Python 3 dal momento che tutte le classi sono di nuovo stile ora; -).

In Python 2, una classe è nuovo stile solo se eredita da un'altra classe di nuovo stile (tra cui object e le varie tipi built-in, come dict, list, set,. ..) o implicitamente o esplicitamente imposta __metaclass__ a type.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top