
L'attributo __bases__ in Python
L'attributo `__bases__` delle classi. Questo attributo ci permette di esplorare l'ereditarietà delle classi, un concetto chiave della programmazione orientata agli oggetti (OOP).
classe.__bases__
L'attributo `__bases__` di una classe è una tupla che contiene le classi base (o superclassi) da cui la classe corrente eredita.
In altre parole, ci dice da quali classi la nostra classe ha ereditato.
In Python, tutto è un oggetto, comprese le classi perché ogni classe in Python è un'istanza della metaclasse `type`. Capire da quali classi una classe eredita può essere molto utile, soprattutto quando si lavora con codice complesso o librerie di terze parti. Ad esempio, possiamo utilizzare `__bases__` per costruire una funzione che esplora la gerarchia di classi in modo ricorsivo:
Vediamo di cosa si tratta e come possiamo utilizzarlo in modo pratico.
Immagina di avere una semplice gerarchia di classi:
class A:
pass
class B(A):
pass
class C(B,A):
pass
In questa gerarchia, la classe `B` eredita da `A` e la classe `C` eredita da `B` e da `A`.
Vediamo cosa ci dice l'attributo `__bases__` per ciascuna di queste classi:
La classe `A` eredita direttamente da `object`, che è la classe base di tutte le classi in Python.
print(A.__bases__)
(<class 'object'>,)
La classe `B` eredita da `A`.
print(B.__bases__)
(<class '__main__.A'>,)
La classe `C` eredita da `B` e poi da `B`.
print(C.__bases__)
(<class '__main__.B'>, <class '__main__.A'>)
Qual è la differenza tra gli attributi base e bases
In breve, la differenza tra questi due attributi simili è la seguente:
- __base__ restituisce la classe base diretta più vicina di una classe. Se la classe eredita da più classi, __base__ restituisce solo la prima classe base diretta secondo l'ordine MRO (Method Resolution Order).
- __bases__ restituisce una tupla contenente tutte le classi base dirette da cui una classe eredita. Se la classe eredita da più classi, __bases__ le include tutte.
Come elencare le classi base in ordine di gerarchia
Per vedere l'elenco delle classi base da cui eredita una classe, seguendo l'ordine gerarchico, puoi definire questa funzione.
def print_class_hierarchy(cls, level=0):
indent = ' ' * (level * 4)
print(f"{indent}{cls.__name__}")
for base in cls.__bases__:
print_class_hierarchy(base, level + 1)
In quest'altro esempio, la funzione `print_class_hierarchy` stampa la gerarchia delle classi a partire da una classe.
Ad esempio, chiama questa funzione sulla classe `C`.
print_class_hierarchy(C)
La funzione restituisce la gerarchia delle classi da cui dipende la classe `C`.
L'indentazione ci aiuta a visualizzare chiaramente i livelli di ereditarietà.
C
B
A
object
In conclusione l'attributo `__bases__` ti permette di capire da quali classi una classe eredita.
Questo è molto utile specialmente in contesti complessi come le grandi librerie o le gerarchie di eccezioni.