Resumo : neste tutorial, você aprenderá sobre encapsulamento e como usar atributos privados para realizar o encapsulamento em Python.
Introdução ao encapsulamento em Python
O encapsulamento é um dos quatro conceitos fundamentais da programação orientada a objetos, incluindo abstração, encapsulamento, herança e polimorfismo.
Encapsulamento é o empacotamento de dados e funções que funcionam nesses dados em um único objeto. Ao fazer isso, você pode ocultar o estado interno do objeto do lado de fora. Isso é conhecido como ocultação de informações .
Uma classe é um exemplo de encapsulamento. Uma classe agrupa dados e métodos em uma única unidade. E uma classe fornece acesso aos seus atributos por meio de métodos.
A ideia de ocultar informações é que se você tiver um atributo que não é visível para o exterior, você pode controlar o acesso ao seu valor para garantir que seu objeto sempre tenha um estado válido.
Vamos dar uma olhada em um exemplo para entender melhor o conceito de encapsulamento.
Exemplo de encapsulamento Python
O seguinte define a Counter
classe:
class Counter:
def __init__(self):
self.current = 0
def increment(self):
self.current += 1
def value(self):
return self.current
def reset(self):
self.current = 0
Linguagem de código: Python ( python )
A Counter
classe tem um atributo chamado current
cujo padrão é zero. E tem três métodos:
increment()
aumenta o valor docurrent
atributo em um.value()
retorna o valor atual docurrent
atributoreset()
define o valor docurrent
atributo como zero.
O seguinte cria uma nova instância da Counter
classe e chama o increment()
método três vezes antes de mostrar o valor atual do contador na tela:
counter = Counter()
counter.increment()
counter.increment()
counter.increment()
print(counter.value())
Linguagem de código: Python ( python )
Saída:
3
Linguagem de código: Python ( python )
Funciona perfeitamente bem, mas tem um problema.
Do lado de fora da Counter
classe, você ainda pode acessar o atributo atual e alterá-lo para o que quiser. Por exemplo:
counter = Counter()
counter.increment()
counter.increment()
counter.current = -999
print(counter.value())
Linguagem de código: Python ( python )
Saída:
-999
Linguagem de código: Python ( python )
Neste exemplo, criamos uma instância da Counter
classe, chamamos o increment()
método duas vezes e definimos o valor do atributo atual como um valor inválido -999
.
Então, como você evita que o current
atributo seja modificado fora da Counter
classe?
É por isso que os atributos privados entram em jogo.
Atributos privados
Atributos privados só podem ser acessíveis a partir dos métodos da classe. Em outras palavras, eles não podem ser acessíveis de fora da classe.
Python não possui um conceito de atributos privados. Em outras palavras, todos os atributos são acessíveis de fora de uma classe.
Por convenção, você pode definir um atributo privado prefixando um único sublinhado (_):
_attribute
Isso significa que o _attribute não deve ser manipulado e pode sofrer alterações significativas no futuro.
O seguinte redefine a Counter
classe com o current
atributo privado por convenção:
class Counter:
def __init__(self):
self._current = 0
def increment(self):
self._current += 1
def value(self):
return self._current
def reset(self):
self._current = 0
Linguagem de código: Python ( python )
Mangling nome com sublinhados duplos
Se você prefixar um nome de atributo com sublinhados duplos ( __
) assim:
__attribute
Python mudará automaticamente o nome do __attribute
para:
_class__attribute
Isso é chamado de mangling em Python.
Ao fazer isso, você não pode acessar o __attribute diretamente de fora de uma classe como:
instance.__attribute
Linguagem de código: CSS ( css )
No entanto, você ainda pode acessá-lo usando o nome _class__attribute:
instance._class__attribute
Linguagem de código: CSS ( css )
O exemplo a seguir redefine a classe Counter com o atributo __current:
class Counter:
def __init__(self):
self.__current = 0
def increment(self):
self.__current += 1
def value(self):
return self.__current
def reset(self):
self.__current = 0
Agora, se você tentar acessar o atributo __current, receberá um erro:
counter = Counter()
print(counter.__current)
Linguagem de código: PHP ( php )
Saída:
AttributeError: 'Counter' object has no attribute '__current'
Linguagem de código: JavaScript ( javascript )
No entanto, você pode acessar o atributo __current como _Counter___current assim:
counter = Counter()
print(counter._Counter__current)
Linguagem de código: PHP ( php )
Resumo
- Encapsulamento é o empacotamento de dados e métodos em uma classe para que você possa ocultar as informações e restringir o acesso externo.
- Prefixe um atributo com um único sublinhado (
_
) para torná-lo privado por convenção. - Prefixe um atributo com sublinhados duplos (
__
) para usar o nome mangling.