Utilizza il polimorfismo e la digitazione anatra prima di isinstance()
In genere si definisce ciò che si desidera fare con le forme, quindi utilizzare il polimorfismo per regolare il modo in cui ciascuna forma risponde a ciò che si desidera eseguire o si utilizza la digitazione anatra; prova se la forma a portata di mano può fare la cosa che vuoi fare in primo luogo. Questa è l'invocazione contro il compromesso dell'introspezione, la saggezza convenzionale afferma che l'invocazione è preferibile rispetto all'introspezione, ma in Python, la tipizzazione dell'anatra è preferibile rispetto al test di isinstance
.
Quindi è necessario capire perché è necessario filtrare la classe in primo luogo; perché hai bisogno di trovare tutti i rettangoli? Forse sono l'unico tipo che implementa un determinato metodo, nel qual caso si utilizza invece la digitazione anatra per testare il metodo.
O forse è necessario elaborare ogni tipo in un modo diverso, perché ogni tipo deve essere gestito correttamente per qualsiasi cosa tu stia facendo con loro. In tal caso, è necessario assegnare a ogni forma lo stesso metodo, ma implementarlo in modo diverso per ciascun tipo, assegnando la responsabilità dell'adattamento in ogni oggetto.
ABC
Con la tipizzazione anatra, potresti scoprire che devi testare per più metodi, quindi un test isinstance()
può sembrare un'opzione migliore. In questi casi, anche l'utilizzo di una Abstract Base Class (ABC) potrebbe essere un'opzione; usando un ABC, per esempio "dipingi" diverse classi come il tipo giusto per una determinata operazione. Usando un ABC, concentriamoci sulle attività che devono essere eseguite piuttosto che sulle specifiche implementazioni utilizzate; puoi avere un Paintable
ABC, un Printable
ABC, ecc.
Interfacce Zope e architettura dei componenti
Se trovi che la tua applicazione utilizza un orribile sacco di ABC o continui a dover aggiungere metodi polimorfici alle tue classi per affrontare diverse situazioni, il passo successivo è considerare l'utilizzo di un architettura di componenti saltati, come Zope Component Architecture (ZCA) .
Le interfacce
zope.interface
sono ABC sugli steroidi, specialmente se combinate con gli adattatori ZCA. Le interfacce documentano il comportamento previsto di una classe:
if IRectangleShape.providedBy(yourshape):
# it's a rectangle
ma ti consentiamo anche di cercare gli adattatori; invece di mettere tutti i comportamenti per ogni uso delle forme nelle classi di forma, si implementano gli adattatori per fornire comportamenti polimorfici per casi d'uso specifici. Puoi adattare le tue forme per essere stampabili, verniciabili o esportabili in XML:
class RectangleXMLExport(object):
adapts(IRectangleShape)
provides(IXMLExport)
def __init__(self, rectangle):
self.rectangle = rectangle
def export(self):
return u'<rectangle><width>{0}</width><height>{0}</height></rectangle>'.format(
self.rectangle.width, self.rectangle.height)
e il tuo codice deve semplicemente cercare gli adattatori per ogni forma:
for shape in shapebag:
self.result.append(IXMLExport(shape).export())