Coletânea Python do ZERO às Redes Neurais Artificiais

Fernando Feltrin · Capítulo 124 de 287

Páginas do PDF

Coletânea Python do ZERO às Redes Neurais Artificiais

Encapsulamento

 

Se você já programa em outras linguagens está habituado a declarar

manualmente em todo início de código, se o bloco de código em questão é de acesso público ou privado. Esta definição em Python é implícita, podendo ser definida manualmente caso haja necessidade.

Por hora, se tratando de programação orientada a objetos, dependendo da finalidade de cada bloco de código, é interessante você definir as permissões de acesso aos mesmos no que diz respeito a sua leitura e escrita.

Digamos que existam determinadas classes acessíveis e mutáveis de acordo com a finalidade e com sua interação com o usuário, da mesma forma existirão classes com seus respectivos métodos que devem ser protegidos para que o usuário não tenha acesso total, ou ao menos, não tenha como modifica-la.

Raciocine que classes e funções importantes podem e devem ser modularizadas, assim como encapsuladas de acordo com sua finalidade, e na prática isto é feito de forma mais simples do que você imagina, vamos ao exemplo:

 

Repare que aqui, inicialmente, estamos criando uma classe como já estamos habituados, neste caso, uma classe chamada BaseDeDados, dentro da mesma há um construtor onde dentro dele simplesmente existe a criação de uma variável na própria instância que pela sintaxe receberá um dicionário, apenas como exemplo mesmo.

Fora da classe é criada uma variável de nome base que inicializa a classe BaseDeDados assim como um comando para exibir o conteúdo de dados.

O ponto chave aqui é, self.dados é uma variável, um atributo de classe que quando declarado sob esta nomenclatura, é visível e acessível tanto dentro dessa instância quanto de fora dela.

 

Note que em nossa função print( ) ao passar como parâmetro base, sua variável dados está disponível para ser instanciada.

A partir do momento que declaramos a variável dados pela sintaxe _dados, a mesma passa a ser uma variável protegida, não visível, ainda acessível de fora da classe, porém implícita.

Repare que ao passar base como parâmetro, dados não está mais visível, ela pode ser declarada manualmente normalmente, porém supondo que este é um código compartilhado, onde os desenvolvedores tem níveis de acesso diferentes ao código, neste exemplo, dados não estaria visível para todos, logo, é um atributo de classe protegido restrito somente a quem sabe sua instância.

Por fim, declarando a variável dados como __dados, a mesma passa a ser privada, e dessa forma, a mesma é inacessível e imutável de fora da classe.

Lembre-se que toda palavra em Python, com prefixo __ (underline duplo) é uma palavra reservada ao sistema, e neste caso não é diferente.

Em resumo, você pode definir a visibilidade de uma variável por meio da forma com que declara, uma underline torna a mesma protegida, underline duplo a torna privada e imutável. Por exemplo:

Apenas pondo em prática o conceito explicado anteriormente, supondo que tenhamos um sistema comercial onde sua programação foi feita sem as devidas proteções de código realizadas via encapsulamento.

Inicialmente é criada uma classe BaseDeDados com um método construtor assim como métodos de classe para inserir, listar e apagar clientes de um dicionário, por meio de seus respectivos nomes e telefones.

Note que nenhum encapsulamento foi realizado (assim como nesse caso, apenas como exemplo, esta base de dados não está modularizada), toda e qualquer parte do código neste momento é acessível e alterável por qualquer desenvolvedor.

Em seguida é criada uma variável que instancia BaseDeDados( ). Dessa forma, é possível por meio dessa variável usar os métodos internos da classe para suas referidas funções, nesse caso, adicionamos 3 clientes a base de dados e em seguida simplesmente pedimos a listagem dos mesmos por meio do método de classe listar.

O retorno será:

Ana 991358899

Fernando 981252001

Maria 999111415

 

Agora simulando uma exceção cometida por um desenvolvedor, supondo que o mesmo pegue como base este código, se em algum momento ele fizer qualquer nova atribuição para a variável relClientes o que ocorrerá é que a mesma atualizará toda a classe quebrando assim todo código interno pronto anteriormente.

 

O retorno será:

 

Isto se deu pelo fato de que, como não havia o devido encapsulamento para proteger a integridade da base de dados, a mesma foi simplesmente substituída pelo novo atributo e a partir desse momento, nenhum bloco de código dos métodos de classe criados anteriormente serão utilizados, uma vez que todos eles dependem do núcleo de self.base que consta no método construtor da classe.

Note que até esse momento ao tentar instanciar qualquer coisa de relClientes, entre os métodos aparece inclusive a base, que deveria ser protegida.

 

Realizando a devida modularização, renomeando todas as referências a base para __base, a partir deste momento a mesma passa a ser um objeto de classe com as devidas proteções de visualização e contra modificação.

 

Executando o mesmo comando print( ) como anteriormente, repare que agora base não aparece mais como um objeto instanciável para um usuário desse nível. Ou que ao menos não deveria ser instanciável.

Porém, ainda assim é possível aplicar mudanças sobre este objeto, mas como ele está definido de forma a ser imutável, o que acontecerá é que o interpretador irá fazer uma espécie de backup do conteúdo antigo, com núcleo protegido e imutável, que pode ser restaurado a qualquer momento.

O interpretador verá que base é uma variável protegida, e que manualmente você ainda assim está forçando atribuir a mesma um novo dado/valor. Sendo assim, evitando uma quebra de código, ele irá executar esta função.

Neste caso, o retorno será Novo Banco de Dados.

Por meio da função print( ), passando como parâmetro _BaseDeDados__base você tem acesso ao núcleo original, salvo pelo interpretador.

Dessa forma o resultado será: {'clientes': {'Ana': 991358899, 'Fernando': 981252001, 'Maria': 999111415}}

Este é um ponto que gera bastante confusão quando estamos aprendendo

 

sobre encapsulamento de estruturas de uma classe.

Visando por convenção facilitar a vida de quem programa, é sempre interessante quando for necessário fazer este tipo de alteração no código deixar as alterações devidamente comentadas, assim como ter o discernimento de que qualquer estrutura de código prefixada com _ deve ser tratada como um código protegido, e somente como última alternativa realizar este tipo de alterações.