Come creare contratti in python

5

Attualmente sto imparando Python (da Java) e ho una domanda sui contratti.

Esempio: un'applicazione definisce un'interfaccia che tutti i plugin devono implementare e quindi l'applicazione principale può chiamarla.

In Java:

public interface IPlugin { 
  public Image modify(Image img); 
} 

public class MainApp {
   public main_app_logic() { 
     String pluginName = "com.example.myplugin"; 
     IPlugin x = (IPlugin) Class.forName(pluginName);
     x.modify(someimg);  
   }
}

Il plugin implementa l'interfaccia e usiamo la riflessione nell'app principale per chiamarla. In questo modo, c'è un contratto tra l'app principale e il plugin a cui entrambi possono fare riferimento.

Come si fa a fare qualcosa di simile in Python? E inoltre, quale approccio è migliore?

P.S. Non sto postando questo su SO perché sono molto più interessato alla filosofia che sta dietro i due approcci.

    
posta recluze 09.12.2012 - 16:42
fonte

2 risposte

8

L'approccio di Python a questo problema riguarda l'approccio opposto a quello di Java.

In Python non ci sono contratti, restrizioni, accordi o requisiti relativi agli oggetti e alle loro capacità. Si presume che un oggetto abbia un determinato metodo o proprietà finché non si tenta effettivamente di usarlo. Se funziona, funziona, ma se l'attributo non esiste, allora si tratta di un errore di runtime. Puoi provare a catturare quel AttributeError prima di far esplodere il tuo programma, oppure puoi eseguire il debug dalla traccia dello stack risultante.

Se il metodo esiste ma restituisce il tipo di risultato errato, allora si spera o otterrai un'eccezione lungo la strada che puoi catturare, o forse otterrai una sorta di output qualche tempo dopo ti avviserai del tuo errore.

Come già detto, puoi utilizzare il modulo abc per definire un Abstract Base Class e registrare la tua classe come implementazione. Questo genererà un TypeError quando istanziate la vostra classe se non implementa tutti i metodi astratti descritti nella vostra classe base astratta. Ovviamente non c'è modo di controllare i tipi di ritorno, dal momento che Python non ha un concetto di tipo restituito.

Questo sottolinea davvero la necessità di una copertura del codice al 100% sui test delle unità per il codice Python. Questi errori possono rimanere tranquillamente inosservati a meno che non si eserciti ogni pezzo di codice in ogni serie di circostanze consentite.

    
risposta data 10.12.2012 - 10:06
fonte
5

Python, essendo un linguaggio di programmazione dinamico, di solito non richiede la rigidità dei contratti Java.

Se stai cercando un registro in stile plugin, la libreria di impacchettamento distribuzione python setuptools fornisce metodi per registrare "punti di ingresso"; utilizzando il modulo pkg_resources (parte del progetto setuptools ) puoi quindi enumerare tutto ciò che è registrato per un determinato punto di ingresso, e diversi pacchetti possono registrare i loro plugin in questo modo. Vedi Spiega i punti di ingresso Python .

Python fornisce 'contratti' di un tipo, chiamati Abstract Base Classes . Il loro scopo è più di test se un oggetto è in grado di soddisfare il contratto e non è normalmente utilizzato per la scoperta.

Ultimo ma non meno importante, i pacchetti aggiuntivi zope.interface e zope.component (parte dell'architettura Zope Component ) fornisce sia un metodo per specificare i contratti, sia i mezzi per cercare componenti registrati come implementazione di un determinato contratto.

    
risposta data 09.12.2012 - 16:59
fonte

Leggi altre domande sui tag