Le Classi in Python

Lezione#10 Benvenuti alla decima lezione del corso Python in 11 passi: sotto i riflettori le Classi.
Le Classi sono gli elementi che stanno alla base del Python e della programmazione orientata agli oggetti. Nelle precedenti lezioni abbiamo visto come attraverso la keyword def è possibile definire un oggetto chiamato funzione. Ora vedremo come con l’istruzione class possiamo definire un oggetto detto classe. Chiariamo quindi meglio il concetto di oggetto.
# script_1001.py lucky = [6, 8, 10, 26, 48] lucky.pop() print(lucky)
[6, 8, 10, 26]
Un oggetto è una struttura dati che può avere attributi e metodi. Nell’esempio precedente, l’oggetto è lucky e pop() è un metodo usato sull’oggetto. Possiamo anche affermare che, essendo Python un linguaggio orientato agli oggetti, ogni cosa è un oggetto! Le Classi sono come dei template (o modelli) per oggetti di un particolare tipo.
# script_1002.py class Car: wheels = 4 #variabile di classe def start_engine(self): print('Vroom!") myCar = Car() #con l'istanza si crea l'oggetto Car
Ricordiamo che un’istanza di un programma è la rappresentazione in memoria della classe a cui l’oggetto corrisponde. Con Car() creiamo un’istanza della classe Car che possiamo memorizzare nella variabile myCar.
Le Funzioni che definiamo con le classi sono anche dette Metodi. Ma a cosa serve l’argomento self?
# script_1003.py class Car: wheels = 4 def start_engine(self): print('Vroom!") myCar = Car() myCar.start_engine()
Vroom!
Il paramentro self punta alla variabile myCar in quanto l’istruzione myCar.start_engine() è l’abbreviazione di Car.start_engine(my_car).
Gli attributi sono condivisi con tutte le istanze, mentre le variabili che definiamo su self appartengono ad una particolare istanza.
# script_1004.py class Car: wheels = 4 def start_engine(self): self.running = True print('Vroom!") myCar = Car() myCar.start_engine()
Vroom!
Il parametro self, quindi indica l’istanza che richiama il metodo, che rende running una cosiddetta variabile di istanza. Inoltre, possiamo definire un metodo speciale __init__ (doppio underscore all’inizio e alla fine di init) che viene invocato quando si “inizializza” una istanza di una classe.
# script_1005.py class Car: wheels = 4 def __init__(self, model) self.model = model self.running = False def start_engine(self): self.running = True print('Vroom!") myCar = Car("Bluesmobile") print(myCar.model)
Bluesmobile
Nello script #1005, si noti come il metodo __init__ vuole sempre il parametro self e viene usato per dare un valore iniziale alle variabili di istanza. Inoltre abbiamo dato in pasto a __init__ un ulteriore parametro (model) e con self.model creiamo l’istanza dell’attributo model della classe Car facendola puntare al parametro model di __init__.
Vediamo un altro esempio di utilizzo delle classi, introducendo il concetto importantissimo di Ereditarietà.
# script_1006.py class Cars: def __init__(self, models): self.models = models def get_model(self): return self.models[0] class Car(Cars): def __init__(self, models): Cars.__init__(self, models) car_one = Car(["Match Patrol", "Bluesmobile", "DeLorean"]) print(car_one.get_model())
Match Patrol
Nell’esempio precedente Car è una sottoclasse di Cars e ne eredita gli attributi. In particolare, in tal caso Car fa le stesse cose di Cars.
# script_1007.py class Cars: def __init__(self, models): self.models = models def get_model(self): return self.models[0] class Car(Cars): def __init__(self, models): Cars.__init__(self, models) def get_model(self): return ", ".join(self.models[1:-1]) cars = Car(["Match Patrol", "Bluesmobile", "DeLorean", "Kit"]) x = cars.get_model() print(x)
Bluesmobile, DeLorean
Ben fatto! Come si può vedere, aggiungendo il metodo get_model() alla sottoclasse Car si sovrascrive lo stesso metodo della classe Cars.
Il metodo join permette di concatenare due o più elementi.
Vediamo un ultimo esempio riepilogativo:
class Vehicle: def __init__(self, name, wheels, engine): self.name = name self.wheels = wheels self.engine = engine def get_card(self): card = f""" Name: {self.name} Wheels: {self.wheels} Engine: {self.engine} """ return card class Car(Vehicle): profile = "Car" def __init__(self, name, wheels, engine, year): super().__init__(name, wheels, engine) self.year = year def get_card(self): card = f""" Profile: {Car.profile} Year: {self.year} """ return super().get_card() + card class Air(Vehicle): profile = "Airplane" def __init__(self, name, wheels, engine, load): super().__init__(name, wheels, engine) self.load = load def get_card(self): card = f""" Profile: {Air.profile} Load: {self.load} """ return super().get_card() + card v_01 = Car("Kit", 4, "Thermal", 1980) v_02 = Air("Jet Pilder", 0, "Hybrid", 1) print(v_01.get_card()) print(v_02.get_card())
Name: Kit
Wheels: 4
Engine: Thermal
Profile: Car
Year: 1980
Name: Jet Pilder
Wheels: 0
Engine: Hybrid
Profile: Airplane
Load: 1
Nello script finale abbiamo creato due sottoclassi (Car e Air) della classe Vehicle. Entrambe le sottoclassi ereditano gli attributi della classe Vehicle. Inoltre abbiamo utilizzato il metodo super() che ci permette di richiamare gli attributi che ci servono dalla classe principale.
Lezione precedente <– []–> Lezione successiva