Le classi sono il pilastro della programmazione orientata agli oggetti . OOP è molto interessato all'organizzazione del codice, alla riusabilità e all'incapsulamento.
Innanzitutto, un disclaimer: OOP è parzialmente in contrasto con la Programmazione Funzionale , che è un paradigma diverso usato molto in Python. Non tutti coloro che programmano in Python (o sicuramente la maggior parte delle lingue) usano OOP. Puoi fare molto in Java 8 che non è molto orientato agli oggetti. Se non vuoi usare OOP, allora non farlo. Se stai solo scrivendo script una tantum per elaborare dati che non utilizzerai mai più, continua a scrivere come sei.
Tuttavia, ci sono molte ragioni per usare OOP.
Alcuni motivi:
Organizzazione: OOP definisce metodi ben noti e standard per descrivere e definire sia i dati che le procedure nel codice. Sia i dati che la procedura possono essere memorizzati a vari livelli di definizione (in diverse classi) e ci sono modi standard di parlare di queste definizioni. Cioè, se usi OOP in modo standard, ti aiuterà a te stesso e agli altri a capire, modificare e usare il tuo codice. Inoltre, invece di utilizzare un meccanismo di archiviazione dei dati complesso e arbitrario (dadi di cubetti o elenchi o cubetti o elenchi di cubetti di insiemi, o qualsiasi altra cosa), è possibile nominare parti di strutture di dati e farvi comodo riferimento ad esse.
Stato: OOP ti aiuta a definire e tenere traccia dello stato. Ad esempio, in un classico esempio, se stai creando un programma che elabora gli studenti (ad esempio, un programma di valutazione), puoi conservare tutte le informazioni che ti servono su di loro in un unico posto (nome, età, sesso, livello, corsi, voti, insegnanti, colleghi, dieta, bisogni speciali, ecc.), e questi dati persistono fintanto che l'oggetto è vivo ed è facilmente accessibile.
Incapsulamento : con l'incapsulamento, procedura e dati sono memorizzati insieme. I metodi (un termine OOP per funzioni) sono definiti accanto ai dati su cui operano e producono. In un linguaggio come Java che consente il controllo dell'accesso o in Python, a seconda di come descrivi l'API pubblica, ciò significa che metodi e dati possono essere nascosti all'utente. Ciò significa che se è necessario o si desidera modificare il codice, è possibile fare tutto ciò che si desidera per l'implementazione del codice, ma mantenere le API pubbliche uguali.
Ereditarietà : l'ereditarietà consente di definire dati e procedure in un unico posto (in una classe) e quindi sostituire o estendere tale funzionalità in un secondo momento. Ad esempio, in Python, vedo spesso persone che creano sottoclassi della dict
classe per aggiungere funzionalità aggiuntive. Una modifica comune è l'override del metodo che genera un'eccezione quando viene richiesta una chiave da un dizionario che non esiste per fornire un valore predefinito basato su una chiave sconosciuta. Ciò consente di estendere il proprio codice ora o in seguito, consentire ad altri di estendere il proprio codice e di estendere il codice di altre persone.
Riusabilità: tutti questi motivi e altri consentono una maggiore riusabilità del codice. Il codice orientato agli oggetti consente di scrivere codice solido (testato) una volta, quindi riutilizzarlo più volte. Se devi modificare qualcosa per il tuo caso d'uso specifico, puoi ereditare da una classe esistente e sovrascrivere il comportamento esistente. Se hai bisogno di cambiare qualcosa, puoi cambiarlo tutto mantenendo le firme del metodo pubblico esistente e nessuno è più saggio (si spera).
Ancora una volta, ci sono diversi motivi per non usare OOP e non è necessario. Ma per fortuna con un linguaggio come Python, puoi usare solo un po 'o molto, dipende da te.
Un esempio del caso d'uso dello studente (nessuna garanzia sulla qualità del codice, solo un esempio):
Orientato agli oggetti
class Student(object):
def __init__(self, name, age, gender, level, grades=None):
self.name = name
self.age = age
self.gender = gender
self.level = level
self.grades = grades or {}
def setGrade(self, course, grade):
self.grades[course] = grade
def getGrade(self, course):
return self.grades[course]
def getGPA(self):
return sum(self.grades.values())/len(self.grades)
# Define some students
john = Student("John", 12, "male", 6, {"math":3.3})
jane = Student("Jane", 12, "female", 6, {"math":3.5})
# Now we can get to the grades easily
print(john.getGPA())
print(jane.getGPA())
Dict standard
def calculateGPA(gradeDict):
return sum(gradeDict.values())/len(gradeDict)
students = {}
# We can set the keys to variables so we might minimize typos
name, age, gender, level, grades = "name", "age", "gender", "level", "grades"
john, jane = "john", "jane"
math = "math"
students[john] = {}
students[john][age] = 12
students[john][gender] = "male"
students[john][level] = 6
students[john][grades] = {math:3.3}
students[jane] = {}
students[jane][age] = 12
students[jane][gender] = "female"
students[jane][level] = 6
students[jane][grades] = {math:3.5}
# At this point, we need to remember who the students are and where the grades are stored. Not a huge deal, but avoided by OOP.
print(calculateGPA(students[john][grades]))
print(calculateGPA(students[jane][grades]))