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
Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!
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)
>> MimiPodemos 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)
>> BobTalvez 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.