Membros Públicos, Protegidos e Privados
Parte da seção Object Oriented Programming do Journey de Python da Coddy — lição 28 de 64.
O Python possui três níveis de controle de acesso para membros de classe: public, protected e private. Estes controlam como atributos e métodos podem ser acessados.
Aqui está um exemplo de uma classe com todos os três níveis de acesso:
class BankAccount:
def __init__(self, owner, balance, account_id):
self.owner = owner # Público - acessível em qualquer lugar
self._balance = balance # Protegido - uso interno
self.__account_id = account_id # Privado - apenas para a classe
def deposit(self, amount): # Método público
self._balance += amount
def _calculate_interest(self): # Método protegido
return self._balance * 0.02
def __validate_transaction(self, amount): # Método privado
return amount > 0 and amount <= self._balanceAcesse membros públicos de qualquer lugar:
account = BankAccount("Alice", 1000, "12345")
print(account.owner) # Alice
account.deposit(500) # Funciona perfeitamenteAcesse membros protegidos (sublinhado simples - apenas convenção):
print(account._balance) # 1500 - funciona, mas não é recomendado
result = account._calculate_interest() # Funciona, mas não é recomendado
print(result) # 30.0Tente acessar membros privados (sublinhado duplo - name mangling):
# Isso não funcionará:
# print(account.__account_id) # AttributeError
# Mas isso funciona (name mangling):
print(account._BankAccount__account_id) # 12345Crie uma subclasse para mostrar o acesso protegido vs privado:
class SavingsAccount(BankAccount):
def show_balance(self):
return self._balance # Protegido - acessível na subclasse
def show_id(self):
# return self.__account_id # Isso não funcionará - privado
return "Cannot access private member"savings = SavingsAccount("Bob", 2000, "67890")
print(savings.show_balance()) # 2000
print(savings.show_id()) # Não é possível acessar o membro privadoSaída:
Alice
30.0
12345
2000
Cannot access private memberPonto Chave: Membros públicos não possuem prefixo e são acessíveis em qualquer lugar. Membros protegidos usam um sublinhado simples (_) e devem ser usados apenas dentro da hierarquia de classes. Membros privados usam sublinhado duplo (__) e passam por name-mangling para uma privacidade mais forte. O controle de acesso do Python é baseado em convenções, não sendo estritamente imposto.
Desafio
MédioNeste desafio, você implementará uma classe BankAccount que demonstra o uso adequado dos níveis de acesso público, protegido e privado em Python.
bankaccount.py- Contém a definição da classe com comentários TODO guiando sua implementação
- Siga os comentários TODO em
bankaccount.pypara implementar a funcionalidade exigida - Implemente os níveis de acesso adequados (público, protegido, privado) conforme especificado
- Certifique-se de que todos os métodos tratem casos extremos adequadamente (depósitos negativos, etc.)
Folha de consulta
O Python possui três níveis de controle de acesso para membros de classe:
- Público: Sem prefixo, acessível em qualquer lugar
- Protegido: Sublinhado único (
_), uso interno dentro da hierarquia de classes - Privado: Sublinhado duplo (
__), com name-mangling para acesso exclusivo à classe
class BankAccount:
def __init__(self, owner, balance, account_id):
self.owner = owner # Público
self._balance = balance # Protegido
self.__account_id = account_id # Privado
def deposit(self, amount): # Método público
self._balance += amount
def _calculate_interest(self): # Método protegido
return self._balance * 0.02
def __validate_transaction(self, amount): # Método privado
return amount > 0 and amount <= self._balanceAcessando membros:
account = BankAccount("Alice", 1000, "12345")
# Acesso público
print(account.owner) # Funciona normalmente
# Acesso protegido (funciona, mas não é recomendado)
print(account._balance) # 1500
# Acesso privado (com name mangling)
print(account._BankAccount__account_id) # 12345Em subclasses:
class SavingsAccount(BankAccount):
def show_balance(self):
return self._balance # Protegido - acessível
def show_id(self):
# return self.__account_id # Privado - não acessível
return "Cannot access private member"Experimente você mesmo
from bank_account import BankAccount
# Manipulador abrangente de casos de teste
test_case = input()
if test_case == "basic_test":
# Teste de funcionalidade básica
account = BankAccount("John Doe", "12345")
print(account.account_holder) # Atributo público
print(account.deposit(100)) # Método público
print(account.get_balance()) # Método público
elif test_case == "transaction_count":
# Testando atributo protegido
account = BankAccount("Jane Smith", "67890")
account.deposit(50)
account.deposit(100)
account.deposit(200)
print(account._transaction_count) # Atributo protegido
print(account.get_balance())
elif test_case == "invalid_deposit":
# Testando validação no método deposit
account = BankAccount("Bob Johnson", "54321")
print(account.deposit(-50)) # Deve retornar None
print(account.deposit(0)) # Deve retornar None
print(account.deposit(75)) # Deve retornar 75
print(account.get_balance())
elif test_case == "private_access":
# Testando acesso a atributo privado
account = BankAccount("Alice Brown", "98765")
try:
print(account.__balance) # Isso lançará um AttributeError
except AttributeError:
pass
try:
print(account.__account_number) # Isso lançará um AttributeError
except AttributeError:
pass
print("Private attributes are not directly accessible")
account.deposit(500)
print(account.get_balance()) # Acesso através de método público
elif test_case == "name_mangling":
# Demonstrando name mangling para atributos privados
account = BankAccount("Charlie Green", "13579")
print(account._BankAccount__balance) # Acessando atributo privado através de name mangling
print(account._BankAccount__account_number) # Acessando atributo privado através de name mangling
account.deposit(300)
print(account._BankAccount__balance) # Deve mostrar o saldo atualizado
elif test_case == "multiple_accounts":
# Testando múltiplas contas
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":
# Teste de desempenho com muitas transações
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}")
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Object Oriented Programming
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosO Parâmetro selfMétodosAtributosMétodo Construtor (__init__)Recapitulação - Calculadora Simples4Herança
Herança BásicaA Função super()Sobrescrita de MétodoHerança MúltiplaOrdem de Resolução de MétodosRecapitulação - Hierarquia de Funcionários7Métodos Especiais
Introdução aos Métodos MágicosSobrecarga de OperadoresMétodos Mágicos de ContêinerRecapitulação - Lista Personalizada10Padrões de Projeto Parte 1
Introdução a Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy2Decoradores
Introdução aos DecoradoresDecorador de PropriedadeDecorador de Método EstáticoDecorador de Método de Classe5Polimorfismo
Sobrescrita de Método RevisitadaDuck TypingClasses e Métodos AbstratosDesign de InterfacesRecapitulação - Calculadora de Formas8Conceitos Avançados de POO
Composição vs HerançaMixinsMétodos Estáticos e de ClasseDecoradores de ClasseGerenciadores de Contexto11Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão Composite3Propriedades de Classe
Variáveis de Instância vs de ClasseDecoradores de PropriedadeAtributos PrivadosRecapitulação - Gerenciador de Conta Bancária6Encapsulamento
Membros Públicos, Protegidos e PrivadosModificadores de AcessoOcultação de InformaçãoProperty Decorators AvançadosRecapitulação - Sistema de Registro de Alunos12Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses Livro e Usuário