Come hai trovato, ci sono molte diverse definizioni di polimorfismo. Questa risposta sarà affrontata da una prospettiva pratica e potrebbe non essere in linea con le definizioni accademiche.
Polimorfismo del sottotipo (via. ereditarietà)
Questo è il tipo di polimorfismo che ritengo la maggior parte delle persone pensa riguardo al termine polimorfismo. Questo è dove i metodi sono ereditati dalle sottoclassi e quindi possono essere sovrascritti. Ad esempio (Python 2.7):
class Foo(object):
def test(self):
print self.name()
def name(self):
return "Foo"
class Bar(Foo):
def name(self):
return "Bar"
foo = Foo()
bar = Bar()
print type(foo)
print type(bar)
print isinstance(bar, type(foo))
Foo().test()
Bar().test()
Output:
<class '__main__.Foo'>
<class '__main__.Bar'>
True
Foo
Bar
Funziona solo il polimorfismo del sottotipo in Java o C #.
Duck Typing
Python ha anche una funzionalità chiamata digitazione anatra. Tecnicamente questa è anche ereditarietà del sottotipo se si distinguono sottotipi ed ereditarietà (che penso sia il modo giusto per pensare a Python) Il termine deriva dal detto idiomatico: "se sembra un'anatra e ciarlatano come un'anatra, è probabilmente un'anatra "che viene spesso abbreviata in" se cova come un'anatra ... "Direi che questo non è il polimorfismo nella letteratura accademica, non importa perché può essere usato per risolvere gli stessi problemi :
class Foo(object):
def test(self):
print "Foo"
class Bar(object):
def test(self):
print "Bar"
foo = Foo()
bar = Bar()
print type(foo)
print type(bar)
print isinstance(bar, type(foo))
Foo().test()
Bar().test()
Output:
<class '__main__.Foo'>
<class '__main__.Bar'>
False
Foo
Bar
Come vedi, possiamo ottenere lo stesso tipo di comportamento di prima, ma ora Bar non è un Foo. La tipizzazione delle anatre è molto comunemente usata nei programmi Python in cui la sub-tipizzazione non lo è. Ad esempio, è comune creare oggetti tipo elenco in cui vengono implementate tutte (veramente: la maggior parte) delle operazioni di list
e vengono passate in metodi come se è come list
pari sebbene da una prospettiva di digitazione pura, non è in realtà un tipo derivato dalla lista.
Polimorfismo parametrico
Prendo questo per dire cose come generici in Java o C #. Non penso che questo sia rilevante per Python, ma non sono veloce su Python 3.
Sovraccarico del metodo
Questo è un caso interessante. Da una prospettiva pura di Python, questo non ha senso perché non è possibile sovraccaricare i metodi. Cioè, non è possibile definire due volte lo stesso nome del metodo. La cosa interessante è che in Jython (python che compila per essere eseguito su JVM) si ottiene una funzionalità che né Java né Python hanno: double-dispatch. Quando si determina quale versione di un metodo Java sovraccarico chiamare da un'istruzione python, il runtime esaminerà i tipi effettivi dei parametri della chiamata e selezionerà la versione in modo dinamico. In Java i metodi sovraccaricati sono invece associati alle chiamate in fase di compilazione, che è tecnicamente polimorfico ma in un modo davvero poco interessante. L'overloading a doppia spedizione può essere effettivamente utilizzato per implementare alcuni effetti interessanti. Mi aspetto che funzioni in modo analogo in IronPython e richiami le librerie C #.
Penso di aver coperto la maggior parte delle basi qui. I commenti sono benvenuti per funzionalità aggiuntive che potrebbero essere considerate polimorfiche. Una cosa di cui non sono sicuro è la possibilità di creare proprietà / metodi sintetici o virtuali usando __getattr__
o __setattr__
et al. Inoltre, penso che potresti rendere l'argomento che il passaggio dei riferimenti ai metodi è un tipo di polimorfismo, ma forse questo sta allungando un po 'troppo le cose.