CodeGym /Curso Java /Python SELF PT /Métodos e campos especiais

Métodos e campos especiais

Python SELF PT
Nível 15 , Lição 5
Disponível

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 :)

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION