Membres Publics, Protégés, Privés
Fait partie de la section Object Oriented Programming du Journey Python de Coddy — leçon 28 sur 64.
Python dispose de trois niveaux de contrôle d'accès pour les membres de classe : public, protected et private. Ceux-ci contrôlent la manière dont les attributs et les méthodes peuvent être accédés.
Voici un exemple d'une classe avec les trois niveaux d'accès :
class BankAccount:
def __init__(self, owner, balance, account_id):
self.owner = owner # Public - accessible partout
self._balance = balance # Protégé - usage interne
self.__account_id = account_id # Privé - classe uniquement
def deposit(self, amount): # Méthode publique
self._balance += amount
def _calculate_interest(self): # Méthode protégée
return self._balance * 0.02
def __validate_transaction(self, amount): # Méthode privée
return amount > 0 and amount <= self._balanceAccédez aux membres publics de n'importe où :
account = BankAccount("Alice", 1000, "12345")
print(account.owner) # Alice
account.deposit(500) # Fonctionne correctementAccéder aux membres protégés (underscore simple - convention uniquement) :
print(account._balance) # 1500 - fonctionne mais n'est pas recommandé
result = account._calculate_interest() # Fonctionne mais n'est pas recommandé
print(result) # 30.0Essayez d'accéder aux membres privés (double soulignement - nom déformé) :
# Cela ne fonctionnera pas :
# print(account.__account_id) # AttributeError
# Mais ceci fonctionne (déformation de nom) :
print(account._BankAccount__account_id) # 12345Créez une sous-classe pour montrer l'accès protégé par rapport à l'accès privé :
class SavingsAccount(BankAccount):
def show_balance(self):
return self._balance # Protégé - accessible dans la sous-classe
def show_id(self):
# return self.__account_id # Cela ne fonctionnera pas - privé
return "Cannot access private member"savings = SavingsAccount("Bob", 2000, "67890")
print(savings.show_balance()) # 2000
print(savings.show_id()) # Impossible d'accéder au membre privéSortie :
Alice
30.0
12345
2000
Cannot access private memberPoint clé : Les membres publics n'ont pas de préfixe et sont accessibles partout. Les membres protégés utilisent un simple souligné (_) et ne devraient être utilisés qu'au sein de la hiérarchie des classes. Les membres privés utilisent un double souligné (__) et subissent un masquage de nom (name-mangling) pour une confidentialité accrue. Le contrôle d'accès de Python est basé sur des conventions et n'est pas strictement appliqué.
Défi
MoyenDans ce défi, vous allez implémenter une classe BankAccount qui démontre l'utilisation appropriée des niveaux d'accès public, protégé et privé en Python.
bankaccount.py- Contient la définition de la classe avec des commentaires TODO guidant votre implémentation
- Suivez les commentaires TODO dans
bankaccount.pypour implémenter la fonctionnalité requise - Implémentez les niveaux d'accès appropriés (public, protégé, privé) comme spécifié
- Assurez-vous que toutes les méthodes gèrent les cas limites de manière appropriée (dépôts négatifs, etc.)
Aide-mémoire
Python dispose de trois niveaux de contrôle d'accès pour les membres de classe :
- Public : Aucun préfixe, accessible partout
- Protégé : Un seul souligné (
_), usage interne au sein de la hiérarchie de classes - Privé : Double souligné (
__), nom déformé (name-mangling) pour un accès réservé à la classe
class BankAccount:
def __init__(self, owner, balance, account_id):
self.owner = owner # Public
self._balance = balance # Protégé
self.__account_id = account_id # Privé
def deposit(self, amount): # Méthode publique
self._balance += amount
def _calculate_interest(self): # Méthode protégée
return self._balance * 0.02
def __validate_transaction(self, amount): # Méthode privée
return amount > 0 and amount <= self._balanceAccès aux membres :
account = BankAccount("Alice", 1000, "12345")
# Accès public
print(account.owner) # Fonctionne correctement
# Accès protégé (fonctionne mais n'est pas recommandé)
print(account._balance) # 1500
# Accès privé (nom déformé)
print(account._BankAccount__account_id) # 12345Dans les sous-classes :
class SavingsAccount(BankAccount):
def show_balance(self):
return self._balance # Protégé - accessible
def show_id(self):
# return self.__account_id # Privé - non accessible
return "Cannot access private member"Essayez vous-même
from bank_account import BankAccount
# Gestionnaire de cas de test complet
test_case = input()
if test_case == "basic_test":
# Test de fonctionnalité de base
account = BankAccount("John Doe", "12345")
print(account.account_holder) # Attribut public
print(account.deposit(100)) # Méthode publique
print(account.get_balance()) # Méthode publique
elif test_case == "transaction_count":
# Test de l'attribut protégé
account = BankAccount("Jane Smith", "67890")
account.deposit(50)
account.deposit(100)
account.deposit(200)
print(account._transaction_count) # Attribut protégé
print(account.get_balance())
elif test_case == "invalid_deposit":
# Test de la validation dans la méthode deposit
account = BankAccount("Bob Johnson", "54321")
print(account.deposit(-50)) # Devrait retourner None
print(account.deposit(0)) # Devrait retourner None
print(account.deposit(75)) # Devrait retourner 75
print(account.get_balance())
elif test_case == "private_access":
# Test de l'accès aux attributs privés
account = BankAccount("Alice Brown", "98765")
try:
print(account.__balance) # Cela lèvera une AttributeError
except AttributeError:
pass
try:
print(account.__account_number) # Cela lèvera une AttributeError
except AttributeError:
pass
print("Private attributes are not directly accessible")
account.deposit(500)
print(account.get_balance()) # Accès via une méthode publique
elif test_case == "name_mangling":
# Démonstration du name mangling pour les attributs privés
account = BankAccount("Charlie Green", "13579")
print(account._BankAccount__balance) # Accès à un attribut privé via le name mangling
print(account._BankAccount__account_number) # Accès à un attribut privé via le name mangling
account.deposit(300)
print(account._BankAccount__balance) # Devrait afficher le solde mis à jour
elif test_case == "multiple_accounts":
# Test de plusieurs comptes
account1 = BankAccount("David White", "24680")
account2 = BankAccount("Eva Black", "86420")
account3 = BankAccount("Frank Red", "97531")
account1.deposit(150)
account2.deposit(250)
account2.deposit(50)
account3.deposit(500)
account3.deposit(300)
account3.deposit(200)
print(f"{account1.account_holder}: {account1.get_balance()}")
print(f"{account2.account_holder}: {account2.get_balance()}")
print(f"{account3.account_holder}: {account3.get_balance()}")
print(f"Account 1 transactions: {account1._transaction_count}")
print(f"Account 2 transactions: {account2._transaction_count}")
print(f"Account 3 transactions: {account3._transaction_count}")
elif test_case == "stress_test":
# Test de performance avec de nombreuses transactions
account = BankAccount("Stress Tester", "11111")
for _ in range(1000):
account.deposit(1)
print(f"Final balance: {account.get_balance()}")
print(f"Transaction count: {account._transaction_count}")
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Object Oriented Programming
1Les fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe paramètre selfMéthodesAttributsMéthode constructeur (__init__)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLa fonction super()Redéfinition de méthodeHéritage multipleOrdre de résolution des méthodesRécapitulatif - Hiérarchie des employés7Méthodes spéciales
Introduction aux méthodes magiquesSurcharge d'opérateursMéthodes magiques de conteneurRécapitulatif - Liste personnalisée10Patrons de conception, Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron Strategy2Décorateurs
Introduction aux décorateursDécorateur de propriétéDécorateur de méthode statiqueDécorateur de méthode de classe5Polymorphisme
Retour sur la redéfinition de méthodeDuck TypingClasses et méthodes abstraitesConception d'interfacesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageMixinsMéthodes statiques et de classeDécorateurs de classeGestionnaires de contexte11Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode TemplatePatron ÉtatPatron Composite3Propriétés de classe
Variables d'instance vs variables de classeDécorateurs de propriétéAttributs privésRécapitulatif - Gestionnaire de compte bancaire6Encapsulation
Membres Publics, Protégés, PrivésModificateurs d'accèsMasquage d'informationsDécorateurs Property AvancésRécapitulatif - Système de Gestion d'Étudiants