Vari concetti di programmazione (da un punto di vista Python)

6

Da quando ho iniziato ad aggirarmi su StackOverflow, continuo a imbattersi in concetti di programmazione come classi astratte, funzioni virtuali, contratti, interfacce, ecc., da domande su altri linguaggi come C ++, Java e C #.

Per quanto ne so io, la maggior parte di queste cose sono legate alla programmazione orientata agli oggetti, ma non sono menzionate tipicamente nelle esercitazioni di Python perché Python usa una combinazione di digitazione anatra e magia per rendere ridondanti tali concetti.

Tuttavia, mi piacerebbe ancora sapere cosa sono.
Cosa sono le classi astratte, le funzioni virtuali, i contratti, le interfacce, ecc. (spiegato da un punto di vista di Python?) Quali altri concetti di programmazione / OOP dovrei sapere che Python di solito non usa o richiede di sapere?

    
posta Michael0x2a 21.01.2012 - 04:13
fonte

3 risposte

11

Classi astratte

Le classi astratte sono classi in cui alcuni metodi sulla classe mancano di implementazioni. Python può (averne) avere questi, ma non sono così espliciti come lingue come Java, dove il programma si rifiuterà di costruire. Tipicamente, si eredita da una classe astratta e si riempiono i pezzi mancanti, eventualmente usando metodi non astratti dalla classe base astratta. Considera questa classe, in Python:

class Foo(object):
    def bar(self):
        # code code code

    def baz(self):
        raise NotImplementedError()

Questa classe è tipo di come una classe astratta: non possiamo (realisticamente) chiamare baz . (Possiamo, ma otterremo solo eccezioni.) A differenza di Java o C ++, dove una classe astratta è una che non può essere istanziata, possiamo istanziare Foo . Python fornisce il modulo abc se vuoi più classi "astratte".

Funzioni virtuali

Le funzioni virtuali sono funzioni che, chiamate da un riferimento o un puntatore a una classe base, chiameranno la versione derivata di quella funzione. In C ++, se ho:

Foo *foo = ClassDerivedFromFoo();
foo->bar();

Se la barra non è virtuale, verrà chiamato Foo::bar . Se lo è, ClassDerivedFromFoo::bar verrà chiamato, se esiste. (La versione più derivata verrà chiamata.)

In Python, una semplificazione eccessiva sarebbe che si possa pensare a tutte le funzioni come virtuali. Questo non è del tutto corretto: le funzioni di un'istanza sono in realtà solo attributi su quell'istanza, e puoi facilmente "convertirle in patch" per essere una funzione arbitraria.

Contratto

Un contratto è un accordo tra una funzione e un chiamante di una funzione riguardo a cose che accadono durante l'esecuzione di una funzione. È essenzialmente la garanzia di una funzione. A mia conoscenza, nessuno di Python / Java / C ++ li applica esplicitamente. Vedi Progetta per contratto .

Interfaccia

In senso sciolto, un'interfaccia è l'API (si noti che l'interfaccia "I" è ) mostra una parte di codice (modulo, classe, funzione, ecc.): consiste di quali chiamate di funzione sono disponibili, quali tipi di dati prendono e restituiscono e quali devono essere i dati da comporre.

Java ha un significato speciale per l'interfaccia: un'interfaccia è una descrizione simile alla classe che contiene funzioni membro che non contengono alcun corpo. Una classe che contiene tutte queste funzioni quindi "implementa" quell'interfaccia. L'interfaccia può essere utilizzata come una classe base di sorta.

Python ha concetti simili, ma molto più astratti. Prendi la funzione enumerate . Richiede un "iterable" e restituisce gli elementi da quel iterable accoppiato con numeri interi crescenti. (Se lo nutrite ['a', 'b', 'c'] sputa (0, 'a'), (1, 'b'), (2, 'c') . Il mio esempio era una lista, ma prenderà felicemente qualsiasi iterable: set, dizionari, generatori, tuple, ecc. Finché l'articolo incontra interfaccia di un iterabile Questa interfaccia non è (in Python) registrata esplicitamente, ma finché l'oggetto che si passa agisce come un iterabile, tutto dovrebbe funzionare (questa è la digitazione anatra).

L'idea di "interfaccia" Java è strettamente correlata all'idea generale di classi base astratte, e alcune delle cose che abc che il modulo può fare potrebbe essere interessante anche per quanto riguarda le interfacce.

    
risposta data 21.01.2012 - 05:16
fonte
6

La maggior parte dei concetti che menzioni non sono usati in Python perché quelli sono concetti legati al legame statico mentre python usa l'associazione dinamica.

Le classi astratte sono clases che non dovrebbero essere utilizzate direttamente, ma devono essere ereditate. Sono utili quando fornisci un'implementazione per alcuni metodi, ma ne manchi uno o più. Dato che Python ha o meno un metodo, ma non può averlo indefinito, non ha senso.

Le funzioni virtuali sono un concetto di C ++. Ogni classe ha una tabella con puntatori alle funzioni, in modo che quando si chiama una funzione il compilatore scrive un puntatore con quello che dovrebbe eseguire. Se dichiari una funzione virtuale, aggiungi un livello di riferimento indiretto; il compilatore non scrive l'indirizzo da eseguire, ma in fase di esecuzione passa alla tabella delle classi, controlla il puntatore e lo esegue. Questo ti permette di usare il polimorfismo (questo è un concetto generico, significa che una funzione è diversa a seconda di quale oggetto lo chiama, esiste in python, cercalo in wikipedia) in modo che se l'oggetto dichiarato è di classe CHILD che ha una funzione virtuale da PARENT utilizza la funzione da BAMBINO e non da PARENT (anche se è un puntatore dichiarato come PARENT). C'è un piccolo prezzo che devi tenere alcuni puntatori e un paio di altre operazioni della CPU, ma è davvero irrilevante

L'interfaccia è fondamentalmente un'operazione che può essere applicata a un oggetto. In linguaggi come Java dichiari un'interfaccia e una classe la implementa. Quindi puoi semplicemente usare oggetti che implementano l'interfaccia in modo indistinto, basta chiamare le funzioni e viene chiamata la funzione appropriata. In Python non hai questo concetto perché chiami semplicemente una funzione e se esiste nell'oggetto è chiamata.

I contratti sono una garanzia di durata stabilita nella documentazione. Ad esempio, in Java esiste un contratto che se compare () restituisce 0 allora equals () dovrebbe restituire true. Non esiste alcuna applicazione (a meno che non si scrivano test per la propria classe), ma si presume che se si ha il metodo compare () e che sia ritornato, 0 equals restituirà true. Se scrivi una classe che rompe il contratto e qualcuno usa, ha un comportamento che è inaspettato. Questo è utile in python; per esempio, puoi scrivere un metodo di ordinamento che si aspetta un elenco di oggetti con 2 funzioni comparabili e uguali, con le condizioni che ho citato per java. Quindi la funzione può ricevere qualsiasi array di oggetti che seguono il contratto, senza sapere nulla sugli oggetti tranne quello. Se passi oggetti che interrompono il contratto, non è garantito cosa accadrà; potresti ottenere l'ordine sbagliato o la funzione potrebbe ricollegarsi continuamente.

    
risposta data 21.01.2012 - 04:37
fonte

Leggi altre domande sui tag