Atributos Privados
Parte da seção Object Oriented Programming do Journey de Python da Coddy — lição 15 de 64.
Atributos privados usam sublinhados para indicar que certos dados não devem ser acessados diretamente de fora da classe.
Por que precisamos de atributos privados? Imagine que você tem uma conta bancária. Você não quer que ninguém altere diretamente o seu saldo - eles devem passar pelos canais adequados (métodos deposit/withdraw) para que o banco possa validar a transação, verificar fraudes, manter registros, etc. Atributos privados funcionam da mesma maneira - eles protegem seus dados de serem alterados incorretamente.
Aqui está um exemplo usando um único sublinhado (convenção para "uso interno"):
class Person:
def __init__(self, name, age):
self._name = name # "protegido" - uso interno
self._age = age # "protegido" - uso internoAtributos com sublinhado único ainda podem ser acessados, mas é um sinal para não fazê-lo:
person = Person("Alice", 30)
print(person._name) # Funciona, mas não é recomendadoUse sublinhados duplos para maior privacidade (name mangling):
class Person:
def __init__(self, name, age):
self.__name = name # "privado" - sofre name mangling
self.__age = age # "privado" - sofre name mangling
def get_name(self):
return self.__name
def set_age(self, age):
if age >= 0:
self.__age = age
else:
print("Age must be positive!")Por que usar métodos getter e setter? Eles são como guardiões. Em vez de permitir que qualquer pessoa altere __age diretamente (o que poderia resultar em idades negativas ou outros dados inválidos), nós os forçamos a usar set_age(), que valida a entrada primeiro. Isso evita bugs e garante a integridade dos dados.
O "código extra" tem um propósito:
get_name()- Acesso controlado para ler o nomeset_age(age)- Valida a idade antes de permitir alterações (sem idades negativas!)- Sem esses métodos, alguém poderia definir
age = -100e quebrar seu programa
Use os métodos acessores para interagir com atributos privados:
person = Person("Bob", 25)
print(person.get_name()) # Bob
person.set_age(30) # Válido: a idade torna-se 30
person.set_age(-5) # Inválido: A idade deve ser positiva! (a idade permanece 30)Viu o benefício? O método set_age() evita dados inválidos. Sem ele, você poderia acidentalmente criar uma pessoa com idade -5, o que não faz sentido!
Atributos com sublinhado duplo sofrem "name mangling", mas ainda podem ser acessados:
person = Person("Charlie", 35)
# Isso não funciona:
# print(person.__name) # AttributeError
# Mas isso funciona (desencorajado):
print(person._Person__name) # CharlieExemplo do mundo real - Por que todo esse código?
class BankAccount:
def __init__(self, balance):
self.__balance = balance # Privado: não pode ser alterado diretamente
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return True
return False
def get_balance(self):
return self.__balance
# Sem atributos privados:
# account.__balance = -1000000 # Desastre! Saldo negativo permitido
# Com atributos privados:
account = BankAccount(100)
account.deposit(50) # Seguro: validado
print(account.get_balance()) # 150O "código extra" (métodos) protege seus dados de alterações inválidas. É como ter seguranças em vez de deixar seus objetos de valor desprotegidos.
Saída:
Alice
Bob
Age must be positive!
Charlie
150Um único sublinhado _attribute significa "apenas para uso interno" por convenção. O sublinhado duplo __attribute aciona o name mangling para uma privacidade mais forte. Use métodos getter/setter (métodos de acesso) para interagir adequadamente com dados privados e adicionar validação. O "código extra" evita bugs ao garantir que os dados sejam sempre válidos.
Desafio
FácilComplete a classe User em user.py com funcionalidade de senha privada e, em seguida, use-a em driver.py. Siga os comentários TODO para implementar os métodos de verificação e alteração de senha.
Folha de consulta
Atributos privados usam sublinhados para indicar que os dados não devem ser acessados diretamente de fora da classe.
Sublinhado único (_attribute) - convenção para "uso interno":
class Person:
def __init__(self, name, age):
self._name = name # "protegido" - uso interno
self._age = age # "protegido" - uso internoSublinhado duplo (__attribute) - aciona a desfiguração de nomes (name mangling) para maior privacidade:
class Person:
def __init__(self, name, age):
self.__name = name # "privado" - sofre desfiguração de nome
self.__age = age # "privado" - sofre desfiguração de nome
def get_name(self):
return self.__name
def set_age(self, age):
if age >= 0:
self.__age = age
else:
print("Age must be positive!")Use métodos de acesso para interagir com atributos privados:
person = Person("Bob", 25)
print(person.get_name()) # Bob
person.set_age(30)
person.set_age(-5) # Age must be positive!Atributos com sublinhado duplo sofrem desfiguração de nome, mas ainda podem ser acessados (desaconselhado):
# Isso não funciona:
# print(person.__name) # AttributeError
# Mas isso funciona (desaconselhado):
print(person._Person__name) # CharlieExperimente você mesmo
# TODO: Importar a classe User do módulo user
# TODO: Obter o caso de teste da entrada
test_case = input()
if test_case == "constructor_test":
# TODO: Criar um objeto User com a senha inicial "secure123"
user = User("secure123")
print("User created successfully")
print("Initial password set")
elif test_case == "correct_password_test":
# TODO: Criar um objeto User com a senha inicial "secure123"
user = User("secure123")
# TODO: Testar o método check_password com a senha correta
# Imprimir "Password check successful!" se retornar True
# Imprimir "Password check failed!" se retornar False
result = user.check_password("secure123")
if result:
print("Password check successful!")
else:
print("Password check failed!")
elif test_case == "incorrect_password_test":
# TODO: Criar um objeto User com a senha inicial "secure123"
user = User("secure123")
# TODO: Testar o método check_password com a senha incorreta "wrong"
# Imprimir "Incorrect password rejected!" se retornar False
# Imprimir "Security issue: incorrect password accepted!" se retornar True
result = user.check_password("wrong")
if not result:
print("Incorrect password rejected!")
else:
print("Security issue: incorrect password accepted!")
elif test_case == "change_password_test":
# TODO: Criar um objeto User com a senha inicial "secure123"
user = User("secure123")
# TODO: Testar a alteração da senha de "secure123" para "newpass456"
# Imprimir "Password changed successfully!" se retornar True
# Imprimir "Password change failed!" se retornar False
result = user.change_password("secure123", "newpass456")
if result:
print("Password changed successfully!")
else:
print("Password change failed!")
# TODO: Verificar se a nova senha funciona testando "newpass456"
# Imprimir "New password works!" se retornar True
# Imprimir "New password doesn't work!" se retornar False
if user.check_password("newpass456"):
print("New password works!")
else:
print("New password doesn't work!")
elif test_case == "change_password_wrong_old_test":
# TODO: Criar um objeto User com a senha inicial "secure123"
user = User("secure123")
# TODO: Tentar alterar a senha com a senha antiga incorreta
# Imprimir "Security working: incorrect old password rejected!" se retornar False
# Imprimir "Security issue: password changed with wrong old password!" se retornar True
result = user.change_password("wrong", "hackerpw")
if not result:
print("Security working: incorrect old password rejected!")
else:
print("Security issue: password changed with wrong old password!")
elif test_case == "comprehensive_test":
# TODO: Criar um objeto User com a senha inicial "secure123"
user = User("secure123")
print("User created with initial password")
# TODO: Testar o método check_password com a senha correta
if user.check_password("secure123"):
print("Initial password verification successful")
# TODO: Testar o método check_password com a senha incorreta
if not user.check_password("wrongpass"):
print("Incorrect password properly rejected")
# TODO: Testar a alteração da senha de "secure123" para "newpass456"
if user.change_password("secure123", "newpass456"):
print("Password successfully changed")
# TODO: Verificar se a senha antiga não funciona mais
if not user.check_password("secure123"):
print("Old password no longer works")
# TODO: Verificar se a nova senha funciona
if user.check_password("newpass456"):
print("New password works correctly")
# TODO: Tentar alterar a senha com a senha antiga incorreta
if not user.change_password("wrongold", "hackerpw"):
print("Security maintained: wrong old password rejected")
# TODO: Verificar se a senha ainda está segura após tentativa de alteração malsucedida
if user.check_password("newpass456"):
print("Password remains secure after failed change attempt")
else:
print("Unknown test case")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