Python - Modificatori di Accesso
Ciao a tutti, aspiranti programmatori Python! Oggi ci imbarqueremo in un viaggio avventuroso nel mondo dei Modificatori di Accesso in Python. Non preoccupatevi se siete nuovi nella programmazione; vi guiderò attraverso questo concetto passo per passo, con un sacco di esempi e spiegazioni lungo il percorso. Allora, immergiamoci!
Modificatori di Accesso in Python
Nella programmazione orientata agli oggetti, i modificatori di accesso vengono utilizzati per controllare la visibilità e l'accessibilità dei membri della classe (attributi e metodi). Mentre molti linguaggi di programmazione hanno modificatori di accesso rigorosi come public, private e protected, Python adotta un approccio più rilassato. Segue una filosofia spesso definita come "Siamo tutti adulti consenzienti qui".
In Python, abbiamo tre tipi di modificatori di accesso:
- Pubblico
- Protetto
- Privato
Esploriamo ciascuno di questi con degli esempi.
Membri Pubblici
In Python, tutti i membri sono pubblici per impostazione predefinita. Questo significa che possono essere accessibili dall'esterno della classe. Ecco un esempio:
class Student:
def __init__(self, name, age):
self.name = name # Attributo pubblico
self.age = age # Attributo pubblico
def display_info(self): # Metodo pubblico
print(f"Name: {self.name}, Age: {self.age}")
# Creazione di un'istanza di Student
student1 = Student("Alice", 20)
# Accesso ai membri pubblici
print(student1.name) # Output: Alice
student1.display_info() # Output: Name: Alice, Age: 20
In questo esempio, name
, age
e display_info()
sono tutti membri pubblici. Possiamo accedervi direttamente dall'esterno della classe.
Membri Protetti
I membri protetti sono denotati prefissando il nome del membro con un singolo underscore (_). Non sono veramente privati e possono ancora essere accessibili dall'esterno della classe, ma è una convenzione trattarli solo per uso interno.
class Employee:
def __init__(self, name, salary):
self._name = name # Attributo protetto
self._salary = salary # Attributo protetto
def _display_salary(self): # Metodo protetto
print(f"{self._name}'s salary is ${self._salary}")
# Creazione di un'istanza di Employee
emp1 = Employee("Bob", 50000)
# Accesso ai membri protetti (Nota: Questo è possibile ma non raccomandato)
print(emp1._name) # Output: Bob
emp1._display_salary() # Output: Bob's salary is $50000
Anche se possiamo accedere a _name
, _salary
e _display_salary()
, generalmente non è consigliabile farlo dall'esterno della classe o delle sue sottoclassi.
Membri Privati
I membri privati sono denotati prefissando il nome con doppie underscores (__). Python esegue il name mangling per questi membri, rendendoli più difficili (ma non impossibili) da accedere dall'esterno della classe.
class BankAccount:
def __init__(self, account_number, balance):
self.__account_number = account_number # Attributo privato
self.__balance = balance # Attributo privato
def __display_balance(self): # Metodo privato
print(f"Balance: ${self.__balance}")
def public_display(self):
self.__display_balance()
# Creazione di un'istanza di BankAccount
account1 = BankAccount("123456", 1000)
# Tentativo di accesso ai membri privati
# print(account1.__account_number) # Questo solleva un AttributeError
# account1.__display_balance() # Questo solleva anche un AttributeError
# Accesso al metodo privato attraverso un metodo pubblico
account1.public_display() # Output: Balance: $1000
In questo esempio, __account_number
, __balance
e __display_balance()
sono membri privati. Tentare di accedervi direttamente dall'esterno della classe solleverà un AttributeError.
Name Mangling
Ricordate quando ho menzionato che i membri privati in Python non sono veramente privati? Questo è a causa di un meccanismo chiamato name mangling. Quando create un membro privato utilizzando doppie underscores, Python cambia il suo nome internamente per rendere più difficile l'accesso accidentale.
Ecco come funziona:
class NameManglingDemo:
def __init__(self):
self.__private_var = "Sono privato!"
demo = NameManglingDemo()
print(dir(demo))
# Output: [..., '_NameManglingDemo__private_var', ...]
# Accesso alla variabile privata utilizzando il nome mangled
print(demo._NameManglingDemo__private_var) # Output: Sono privato!
Come vedete, Python rinomina __private_var
in _NameManglingDemo__private_var
. Questo è il name mangling in azione!
Oggetto Proprietà di Python
La funzione property()
in Python è una funzione integrata che crea e restituisce un oggetto proprietà. È un modo per aggiungere metodi getter, setter e deleter agli attributi della classe.
Ecco un esempio:
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
def get_fahrenheit(self):
return (self._celsius * 9/5) + 32
def set_fahrenheit(self, fahrenheit):
self._celsius = (fahrenheit - 32) * 5/9
fahrenheit = property(get_fahrenheit, set_fahrenheit)
# Utilizzo della proprietà
temp = Temperature(25)
print(temp.fahrenheit) # Output: 77.0
temp.fahrenheit = 86
print(temp._celsius) # Output: 30.0
In questo esempio, fahrenheit
è una proprietà che ci consente di ottenere e impostare la temperatura in Fahrenheit memorizzandola internamente in Celsius.
Metodi Getter e Setter
I metodi getter e setter sono metodi utilizzati per ottenere e impostare i valori degli attributi della classe. Forniscono un modo per accedere e modificare gli attributi privati mantenendo l'incapsulamento.
Ecco un esempio utilizzando il decoratore @property
, che è un modo più pythonesco di implementare i getter e i setter:
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if not isinstance(value, str):
raise ValueError("Il nome deve essere una stringa")
self._name = value
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if not isinstance(value, int) or value < 0:
raise ValueError("L'età deve essere un intero positivo")
self._age = value
# Utilizzo di getter e setter
person = Person("Charlie", 30)
print(person.name) # Output: Charlie
person.name = "David"
print(person.name) # Output: David
try:
person.age = -5
except ValueError as e:
print(e) # Output: L'età deve essere un intero positivo
In questo esempio, abbiamo creato metodi getter e setter per name
e age
. I metodi setter includono la validazione per assicurarsi che i valori impostati soddisfino determinati criteri.
Per riassumere i metodi discussi, ecco una tabella in formato Markdown:
Metodo | Descrizione | Esempio |
---|---|---|
Pubblico | Accessibile da ovunque | self.name |
Protetto | Accessibile all'interno della classe e delle sottoclassi (per convenzione) | self._name |
Privato | Nome mangled per limitare l'accesso | self.__name |
Proprietà | Crea un oggetto proprietà | property(get_method, set_method) |
Getter | Metodo per ottenere il valore di un attributo | @property |
Setter | Metodo per impostare il valore di un attributo | @attribute.setter |
Eccoci! Abbiamo coperto i modificatori di accesso in Python, il name mangling, gli oggetti proprietà e i metodi getter e setter. Ricordate, l'approccio di Python al controllo dell'accesso è più sulla convenzione e la fiducia che su regole rigorose. Mentre continuate il vostro viaggio con Python, scoprirete che questa flessibilità permette di scrivere codice pulito e leggibile mentre fornisce ancora modi per implementare l'incapsulamento quando necessario.
Seguite a praticare, restate curiosi e buon coding!
Credits: Image by storyset