Fiz os cursos de formação em python e fiquei em dúvida qual convenção usar para um atributo privado?
Dois underscore --> __atributo ou um underscore --> _atributo
Fiz os cursos de formação em python e fiquei em dúvida qual convenção usar para um atributo privado?
Dois underscore --> __atributo ou um underscore --> _atributo
Oi Wellington, como você está? Espero que esteja bem ^-^
Segundo a documentação da linguagem, a convenção é um único underscore(_atributo). Abaixo, um pequeno trecho da documentação:
"Variáveis de instância “privadas”, que não podem ser acessadas, exceto em métodos do próprio objeto, não existem em Python. No entanto, existe uma convenção que é seguida pela maioria dos programas em Python: um nome prefixado com um sublinhado (por exemplo: _spam )"
E qual a diferença em usar um underscore ao invés de dois?
Quando utilizamos o duplo underscore acontece um fenômeno chamado de name mangling que se refere ao Python modificar o nome do atributo para dificultar o seu acesso direto e também, para evitar conflitos de nomes em subclasses, então qualquer variável dentro da classe no formato __variavel
será substituído por _nomedaclasse__variavel
. Vamos ver um exemplo em código para ficar mais claro, tá?
Animal
:class Animal:
def __init__(self):
self.__cachorro = "Bob"
self._gato = "Mimi"
Agora, vamos confirmar que o Python realmente modifica o atributo com o duplo underscore e podemos fazer isso imprimindo todos os atributos e métodos daquele objeto através do comando dir, veja:
objeto_animal = Animal()
print(dir(objeto_animal))
Como saída teremos:
['_Animal__cachorro', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__weakref__', '_gato']
Observe que temos _Animal__cachorro
na listagem, que se refere a variável __cachorro
modificada, pois ela estava com o duplo underscore. Se tentarmos acessar diretamente o atributo __cachorro
não iremos conseguir, dará erro de atributo dizendo que a classe Animal não possui o atributo __cachorro
e isso ocorre porque internamente o Python modificou esse atributo para a nomenclatura que foi mostrada: _Animal__cachorro
:
>> print(objeto_animal.__cachorro)
>> AttributeError: 'Animal' object has no attribute '__cachorro'
Agora, se tentarmos acessar o atributo com um único underscore iremos conseguir tranquilamente, veja:
>> print(objeto_animal._gato)
>> Mimi
Podemos também acessar o atributo com o duplo underscore, mas é necessário o conhecimento de saber que o Python irá modificar esse atributo pelo fato de estar com o duplo underscore. Em código fica algo como:
>> print(objeto_animal._Animal__cachorro)
>> Bob
Talvez fui além do que você perguntou, mas a ideia é que você saiba que em Python não existe atributo 100% privado, sempre teremos como acessá-lo, a convenção é apenas para que outros programadores saibam que há uma norma a seguir e que não é interessante acessar aquele atributo fora da classe. Tudo bem?!
Welligton, se tiver ficado alguma dúvida é só falar, estou por aqui, tá bom?
Abraços!
Muito obrigado! Já entendi.