Non esiste un loop infinito reale, perché il metodo __call__
non è effettivamente invocato ("chiamato") per tutte queste situazioni. Viene invocato direttamente solo quando c'è una chiamata simile a una funzione su un oggetto che fornisce un metodo __call__
.
L'istanza di classe normale Cls(...)
e l'invocazione funzionale regolare f()
sono casi noti gestiti direttamente. C'è generalmente non è una chiamata effettiva di __call__()
, quindi ci sono un numero finito di __call__
invocazioni di metodi che possono verificarsi mai, anche nei casi complessi con ereditarietà profondo, metaclassi, ecc
Poiché c'era qualche controversia se la il cortocircuito dei loop infiniti concettuali stava davvero accadendo, diamo un'occhiata al bytecode smontato. Si consideri il seguente codice:
def f(x):
return x + 1
class Adder(object):
def something(self, x):
return x + 19
def __call__(self, x):
return x + 1
def lotsacalls(y):
u = f(1)
a = Adder()
z = u + a.something(y)
return a(z * 10)
dispiace è un po 'complessa, come voglio mostrare diversi casi di corto circuito - vale a dire, le normali funzioni def
, __init__
chiamate, i metodi normali, e __call__
metodi speciali. Ora:

Così qui sono una serie di momenti in cui, se Python erano veramente, veramente "a piedi l'albero" di concettuali __call__
invocazioni, sarebbe fare riferimento Function
(e possibilmente Method
classi, e richiamare la loro Metodi __call__
). Non è così. Utilizza il semplice codice bytecode CALL_FUNCTION
in tutti i casi, cortocircuitando l'albero concettuale a piedi in basso. Logicamente si può immaginare che esiste una classe Function
che ha un metodo __call__
che viene richiamato quando viene chiamata una funzione (ad esempio un'istanza della classe Function
). Ma in realtà non funziona in questo modo. Il compilatore, l'interprete bytecode e altre parti delle sottostringhe in linguaggio C non sono in realtà alberi meta-classe a piedi. Fanno un corto circuito come un matto.
fonte
2015-09-30 00:45:33
Ah grazie! Tutto ha senso ora: D –