Python nos dá a capacidade de criar métodos 'privados' e variáveis dentro de uma classe, antecedendo sublinhados duplos para o nome, assim: __myPrivateMethod()
. Como, então, alguém pode explicar isso?
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
Qual é o problema ?!
Vou explicar isso um pouco para quem não entendeu direito.
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
O que eu fiz lá é criar uma classe com um método público e um método privado e instancia-lo.
Em seguida, chamo seu método público.
>>> obj.myPublicMethod()
public method
Em seguida, tento chamar seu método privado.
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
Tudo parece bom aqui; não podemos chamá-lo. É, de fato, "privado". Bem, na verdade não é. A execução de dir () no objeto revela um novo método mágico que o python cria magicamente para todos os seus métodos 'particulares'.
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
O nome desse novo método é sempre um sublinhado, seguido pelo nome da classe, seguido pelo nome do método.
>>> obj._MyClass__myPrivateMethod()
this is private!!
Tanta coisa para encapsulamento, não é?
De qualquer forma, sempre ouvi dizer que o Python não suporta encapsulamento, então por que tentar? O que da?
Respostas:
A codificação de nomes é usada para garantir que as subclasses não substituam acidentalmente os métodos e atributos particulares de suas superclasses. Ele não foi projetado para impedir o acesso deliberado de fora.
Por exemplo:
Obviamente, ele será quebrado se duas classes diferentes tiverem o mesmo nome.
fonte
Exemplo de função privada
fonte
self = MyClass()
self.private_function()
. : D Claro que não funciona nas aulas, mas você só tem que definir uma função personalizada:def foo(self): self.private_function()
function_call.startswith('self.')
.inspect.stack()[1][4][0].strip()
<- quais são os números mágicos 1, 4 e 0?self = MyClass(); self.private_function()
e falha quando chamado usandox = self.private_function()
dentro de um método.Quando eu vim de Java para Python, odiei isso. Isso me assustou até a morte.
Hoje, essa pode ser a única coisa que eu mais amo no Python.
Adoro estar em uma plataforma, na qual as pessoas confiam umas nas outras e não sentem que precisam criar muros impenetráveis em torno de seu código. Em linguagens fortemente encapsuladas, se uma API tiver um bug e você tiver descoberto o que está errado, você ainda poderá não conseguir solucionar o problema, porque o método necessário é privado. Em Python, a atitude é: "com certeza". Se você acha que entende a situação, talvez até a tenha lido, tudo o que podemos dizer é "boa sorte!".
Lembre-se de que o encapsulamento não está nem um pouco relacionado à "segurança" ou a manter as crianças fora do gramado. É apenas outro padrão que deve ser usado para facilitar a compreensão de uma base de código.
fonte
Em http://www.faqs.org/docs/diveintopython/fileinfo_private.html
fonte
A frase comumente usada é "somos todos adultos concordantes aqui". Anexando um único sublinhado (não exponha) ou o sublinhado duplo (ocultar), você está dizendo ao usuário da sua classe que pretende que o membro seja 'privado' de alguma forma. No entanto, você está confiando que todos os demais devem se comportar com responsabilidade e respeitar isso, a menos que eles tenham um motivo convincente para não fazê-lo (por exemplo, depuradores de código, conclusão de código).
Se você realmente deve ter algo privado, pode implementá-lo em uma extensão (por exemplo, em C para CPython). Na maioria dos casos, no entanto, você simplesmente aprende a maneira pitônica de fazer as coisas.
fonte
Não é como se você absolutamente não pudesse contornar a privacidade dos membros em qualquer idioma (aritmética de ponteiros em C ++, Reflexões em .NET / Java).
O ponto é que você receberá um erro se tentar chamar o método privado por acidente. Mas se você quer dar um tiro no pé, vá em frente e faça-o.
Edit: Você não tenta proteger suas coisas por encapsulamento OO, não é?
fonte
A
class.__stuff
convenção de nomenclatura permite que o programador saiba que ele não deve acessar__stuff
de fora. O nome desconcertante torna improvável que alguém o faça por acidente.É verdade que você ainda pode solucionar isso, é ainda mais fácil do que em outras linguagens (que a BTW também permite), mas nenhum programador Python faria isso se ele se importasse com o encapsulamento.
fonte
Um comportamento semelhante existe quando os nomes dos atributos do módulo começam com um único sublinhado (por exemplo, _foo).
Os atributos do módulo nomeados como tal não serão copiados para um módulo de importação ao usar o
from*
método, por exemplo:No entanto, esta é uma convenção e não uma restrição de idioma. Esses não são atributos particulares; eles podem ser referenciados e manipulados por qualquer importador. Alguns argumentam que, por causa disso, o Python não pode implementar o verdadeiro encapsulamento.
fonte
É apenas uma dessas opções de design de idioma. Em algum nível, eles são justificados. Eles fazem com que você precise ir muito longe do seu caminho para tentar chamar o método, e se você realmente precisa muito disso, deve ter um bom motivo!
Ganchos de depuração e testes vêm à mente como possíveis aplicativos, usados com responsabilidade, é claro.
fonte
Com o Python 3.4, este é o comportamento:
https://docs.python.org/3/tutorial/classes.html#tut-private
Mesmo se a pergunta for antiga, espero que meu snippet possa ser útil.
fonte
A preocupação mais importante sobre métodos e atributos privados é dizer aos desenvolvedores para não chamá-lo fora da classe e isso é encapsulamento. pode-se entender mal a segurança do encapsulamento. quando alguém usa deliberadamente uma sintaxe como essa (abaixo) mencionada, não deseja encapsulamento.
Eu migrei do C # e no começo era estranho para mim também, mas depois de um tempo cheguei à ideia de que apenas a maneira como os designers de código Python pensam sobre OOP é diferente.
fonte
Pelo que entendi, eles não podem ser privados. Como a privacidade pode ser aplicada?
A resposta óbvia é que "membros privados só podem ser acessados por meio
self
", mas isso não funcionaria -self
não é especial no Python, nada mais é que um nome comumente usado para o primeiro parâmetro de uma função.fonte