Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Dúvida sobre versão atual do Python 3.10.1

Estou fazendo este curso atualmente com a versão 3.10.1 do Python e quando eu declaro os atributos como sendo privados, era de se esperar como dito nas aulas que estes atributos ainda poderiam ser acesssados fora da classe, no entanto, isso nao ocorre, os atributos ficam inacessíveis para alteração, so podendo voltar a ser modificados quando elimino a declaração de privados. Gostaria de saber se isso tem a ver com a versão atual que estou usando e se este acesso foi modificado ?

7 respostas

Todos os atributos de classe são acessáveis, mesmo os "privados". Estes são apenas obfuscados, a questão é de que forma acessá-los.

No código abaixo é declarado o "atributo" privado, e o mesmo pode ser alterado através de teste._MinhaClass__atributo.

class MinhaClass:
    def __init__(self, atributo) -> None:
        self.__atributo = atributo

    @property
    def atributo(self):
        return self.__atributo


teste = MinhaClass('original')
teste._MinhaClass__atributo = 'alterado'

print(teste.atributo) # alterado

Sempre que tiver dúvida sobre o funcionamento de algo use os comandos dir e help. No caso descrito, você encontrará o nome real do "atributo" acessando dir(teste) ou dir(MinhaClass)

Estou gostando muito do Python, mas achei essa solução de atributo privado muito fraca em termos de segurança. Apesar de chamar a atenção devido ao estilo do nome do atributo, infelizmente ele ainda permite acesso tanto de leitura como de escrita. Isso acaba atrapalhando uma das grandes vantagens da OO, que é garantir a integridade do objeto. Quanto ao teste, estou usando a versão 3.10.2 e ele ainda me permite acessar os atributos "privados" (realmente entre aspas) e alterar seus valores.

Eu também acho uma solução muito fraca, Rodolfo. Concordo com você em todos os pontos, isso enfraquece o OO.

Sinceramente não me parece que isto será alvo de mudança em versões futuras.

Acabei de ver a parte sobre @property, que ajuda um pouco, mas não resolve o problema. Minha maior preocupação é como garantir as regras de negócio se outro programador poderá "pular" essas regras, pois terá acesso direto à informação. Não que seja uma grande preocupação quando se trabalha em equipe, mas espero que consigam melhorar essa implementação de OO nas próximas versões.

Especificamente no exerício que eles colocaram, envolvendo saldo, é terrível que alguém possa "setar" um saldo sem passar pelas operações de depósito, saque ou transferência. Espero que, à medida que o curso evoluir, a gente aprenda que existe uma forma de resolver isso, evitando essas manipulações diretas.

solução!

Filipe, fiz uns testes aqui e parece que o problema está resolvido (pelo menos na 3.10.2 que estou usando). Montei um código para testar e o acesso ao __limite simplesmente sumiu. Acredito que ao usar o @property ele esconde aquela informação com __, gerando mais segurança no acesso aos atributos. O código é esse:

class Conta:
    def __init__(self, numero, titular, saldo, limite):
        self.__numero = numero
        self.__titular = titular
        self.__saldo = saldo
        self.__limite = limite

    @property
    def limite(self):
        return(self.__limite)

    @limite.setter
    def limite(self, valor):
        self.__limite = valor

    @property
    def saldo(self):
        return(self.__saldo)

    def deposita(self, valor):
        self.__saldo += valor

    def saca(self, valor):
        self.__saldo -= valor

    def extrato(self):
        return (self.__saldo)

    def transfere(self, valor, conta):
        self.__saldo -= valor
        conta.deposita(valor)

conta = Conta(123,"Marco",1000,5000)
conta.limite = 2500
print(conta.limite)
print(conta.__limite)

Dá erro no último comando: Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Isso, a ideia é obfuscar, mas é apenas um artifício.

Ainda é possível acessar e alterar o atributo privado através de conta._Conta__limite.