Andre,
Cara, no python como o professor falou, não existe atributo 100% privado. Assim, por convenção, quando utilizamos o _ no inicio de Uma variável, as ide descentes, como Pycharm e Atom por exemplo, não mostram elas no autocomplete.
Em linguagens como Java e C# basta declarar que os atributos não podem ser acessados de fora da classe utilizando a palavra chave private. Em orientação a objetos, é prática quase que obrigatória proteger seus atributos com private. Cada classe é responsável por controlar seus atributos, portanto ela deve julgar se aquele novo valor é válido ou não. E esta validação não deve ser controlada por quem está usando a classe e sim por ela mesma, centralizando essa responsabilidade e facilitando futuras mudanças no sistema.
O Python não utiliza o termo private, que é um modificador de acesso e também chamado de modificador de visibilidade. No Python inserimos dois underscores ('__') ao atributo para adicionar esta característica:
class Pessoa:
def __init__(self, idade):
self.__idade = idade
Dessa maneira não conseguimos acessar o atributo idade de um objeto do tipo Pessoa fora da classe:
pessoa = Pessoa(20)
pessoa.idade
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'Pessoa' object has no attribute 'idade'
O interpretador acusa que o atributo idade não existe na classe Pessoa. Mas isso não garante que ninguém possa acessá-lo. No Python não existem atributos realmente privados, ele apenas alerta que você não deveria tentar acessar este atributo, ou modificá-lo. Para acessá-lo, fazemos:
>>> p._Pessoa__idade
Ao colocar o prefixo _ no atributo da classe, o Python apenas renomeia '__nomedo_atributo' para 'nomedaClasse_nome_do_atributo', como fez em idade para _Pessoaidade. Qualquer pessoa que saiba que os atributos privados não são realmente privados, mas "desconfigurados", pode ler e atribuir um valor ao atributo "privado" diretamente. Mas fazer pessoa.Pessoa_idade = 20 é considerado má prática e pode acarretar em erros.
Podemos utilizar a função dir para ver que o atributo Pessoa_idade pertence ao objeto:
dir(pessoa)
['Pessoa__idade', 'class', 'delattr', 'dict', 'dir',
'doc', 'eq', 'format', 'ge', 'getattribute', 'gt',
'hash', 'init', '__initsubclass__', 'le', 'lt',
'module', 'ne', 'new', 'reduce', 'reduce_ex',
'repr', 'setattr', 'sizeof', 'str', 'subclasshook',
'weakref']
FONTE: https://www.caelum.com.br/apostila-python-orientacao-objetos/encapsulamento/