2010-02-23 3 views
13

corse in quanto segue:a == b è falso, ma id (a) == id (b) è vero?

>>> class A: 
...  def __str__(self): 
...    return "some A()" 
... 
>>> class B(A): 
...  def __str__(self): 
...    return "some B()" 
... 
>>> print A() 
some A() 
>>> print B() 
some B() 
>>> A.__str__ == B.__str__ 
False # seems reasonable, since each method is an object 
>>> id(A.__str__)==id(B.__str__) 
True # what?! 

cosa sta succedendo qui?

risposta

8

le seguenti opere:

>>> id(A.__str__.im_func) == id(A.__str__.im_func) 
True 
>>> id(B.__str__.im_func) == id(A.__str__.im_func) 
False 
+0

Nota: questa risposta funziona solo per Python 2. – BenC

11

Come la stringa id(A.__str__) == id(B.__str__) viene valutata, A.__str__ viene creato, il suo ID, quindi al garbage collection. Quindi viene creato B.__str__, e capita di trovarsi allo stesso identico indirizzo che era A.__str__ in precedenza, quindi ottiene (in CPython) lo stesso id.

Provate ad assegnare A.__str__ e B.__str__ di variabili temporanee e vedrete qualcosa di diverso:

>>> f = A.__str__ 
>>> g = B.__str__ 
>>> id(f) == id(g) 
False 

Per un esempio più semplice di questo fenomeno, provare:

>>> id(float('3.0')) == id(float('4.0')) 
True 
+0

Ma allora, perché >>> f = A .__ str__ >>> id (f) == ID (un .__ str__) Falso – Krab

+0

'A. __str__' è stato creato ??? Non sono sicuro di questo: deve essere parte del metaclass che genera tutte le classi, cioè il loro "DNA" di base. – jldupont

+2

@jldupont: Python crea i metodi non associati 'A .__ str__' e' B .__ str__' in fase di runtime. http://users.rcn.com/python/download/Descriptor.htm è un buon riferimento per i meccanismi sottostanti. –

0

Per quelli di noi qui attratti dal titolo, per determinare se un metodo è stato ignorato:

class A: 
    def __str__(self): 
     return "some A()" 

    def strWasOverridden(self): 
     return A.__str__ != self.__str__ 
+0

In realtà, no. Questo è sempre vero, perché un'istanza su un metodo non è mai uguale a un metodo su una classe. –