5.1 Níveis de acesso
Você deve ter notado o nome estranho do construtor
__init__
? No futuro você vai encontrar isso bastante.
Em Python existem diferentes níveis de acesso aos
atributos e métodos das classes, que ajudam a controlar
a visibilidade e proteção dos dados. Os principais mecanismos de controle
de acesso incluem o uso de um ou dois sublinhados (_
e
__
) antes do nome do atributo ou método.
Uso de convenções
Um sublinhado _
é usado para atributos e
métodos que não devem ser usados fora da classe ou módulo. Isso
não é proibido, mas é uma convenção que deve ser seguida para
melhor legibilidade e manutenção do código.
Dois sublinhados __
são usados para atributos e
métodos que devem ser realmente privados e protegidos
de acesso acidental ou intencional de fora. O mecanismo name
mangling
os torna menos acessíveis, mas ainda disponíveis através
de nomes especiais.
Campos e métodos (public)
públicos
Atributos e métodos públicos
estão acessíveis de qualquer lugar do código
. Em
Python por padrão todos os atributos e métodos são públicos, se
seus nomes não começarem com sublinhado.
class MyClass:
def __init__(self):
self.public_attribute = "I am public"
def public_method(self):
return "This is a public method"
obj = MyClass()
print(obj.public_attribute) # Acessível
print(obj.public_method()) # Acessível
Através dos níveis de acesso na linguagem Python é realizada a encapsulação, precisamente através de campos e métodos não públicos.
5.2 Campos e métodos não públicos
Campos e métodos (protected)
protegidos
Atributos e métodos protegidos são indicados por um
sublinhado _
antes do nome e são destinados ao uso interno
na classe e suas subclasses. É uma convenção que
indica aos programadores que os dados não são destinados ao
uso fora da classe.
class MyClass:
def __init__(self):
self._protected_attribute = "I am protected"
def _protected_method(self):
return "This is a protected method"
obj = MyClass()
print(obj._protected_attribute) # Acessível, mas não recomendado
print(obj._protected_method()) # Acessível, mas não recomendado
Campos e métodos (private)
privados
Em Python, atributos e métodos privados são indicados por dois sublinhados __
antes do nome. Esses atributos e métodos são destinados ao uso exclusivo dentro da classe, e seu principal objetivo é ocultar a implementação interna e proteger os dados contra alteração acidental ou uso externo.
Para prevenir acesso direto a esses atributos e métodos a partir de código externo, Python aplica um mecanismo especial conhecido como name mangling
(distorção de nome). Esse mecanismo automaticamente altera os nomes dos atributos privados, adicionando um prefixo composto pelo nome da classe. Assim, o atributo privado __private_attribute
na classe MyClass
será transformado em um nome interno _MyClass__private_attribute
.
Isso permite proteger os dados contra acesso não intencional, mantendo a possibilidade de trabalhar com eles dentro da classe. No entanto, é importante lembrar que o mecanismo "name mangling"
não é uma proteção absoluta - um programador experiente pode acessar esses dados usando o nome alterado.
Vamos ver como isso funciona na prática:
class MyClass:
def __init__(self):
self.__private_attribute = "I am private"
def __private_method(self):
return "This is a private method"
def access_private_method(self):
return self.__private_method()
obj = MyClass()
# print(obj.__private_attribute) # Erro, não acessível diretamente
# print(obj.__private_method()) # Erro, não acessível diretamente
print(obj.access_private_method()) # Acessível através de método público da classe
Como pode ser visto no exemplo, o acesso direto a atributos ou métodos privados gera um erro. Mas Python mantém a possibilidade de acesso a eles através do nome alterado. Por exemplo, você pode acessar o atributo privado usando o nome "distorcido", como mostrado abaixo:
class MyClass:
def __init__(self):
self.__private_attribute = "I am private"
obj = MyClass()
print(obj._MyClass__private_attribute) # Irá imprimir: I am private
Embora o acesso através do nome "distorcido" seja possível, deve ser evitado, pois isso viola os princípios de encapsulamento e pode levar a instabilidade no código.
Para ver como Python altera os nomes dos atributos, você pode usar a função embutida dir()
, que exibe todos os atributos e métodos disponíveis de um objeto:
class MyClass:
def __init__(self):
self.__private_attribute = "I am private"
obj = MyClass()
print(dir(obj)) # Exibe todos os atributos e métodos do objeto, incluindo nomes "distorcidos"
Como resultado da execução da função dir()
, você verá uma lista de todos os atributos e métodos do objeto, incluindo _MyClass__private_attribute
, o que confirma o mecanismo de "name mangling"
.
5.3 Chamada automática de métodos
Houve um aspecto interessante ao trabalhar com construtores que
você pode ter notado. O método __init__
foi chamado automaticamente.
Na verdade há bastante dessas situações, assim como métodos para esses casos. Exemplos:
Método __str__
Se seu objeto possui o método __str__
, ele será chamado
automaticamente ao tentar converter seu objeto em uma string,
por exemplo, ao usar as funções print()
e
str()
.
class Cat:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name} is {self.age} years old"
cat = Cat("Barsik", 5)
print(cat) # Irá imprimir: Barsik is 5 years old
Método __len__
E se o seu objeto tem o método __len__
, ele será chamado automaticamente ao tentar
determinar o "comprimento" do seu objeto - usado pela função len()
. Exemplo:
class MyList:
def __init__(self, items):
self.items = items
def __len__(self):
return len(self.items)
my_list = MyList([1, 2, 3])
print(len(my_list)) # Irá imprimir: 3
Você ainda vai encontrar muitos desses "métodos especiais" na sua vida, mas trabalhar com eles é uma satisfação só. Então prepare-se :)
GO TO FULL VERSION