Pergunta

Python nos dá a capacidade de criar 'privado' métodos e variáveis dentro de uma classe, inserindo duplo sublinhado para o nome, como este: __myPrivateMethod().Como, então, explicar essa

>>> 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!!

O que é o negócio?!

Vou explicar um pouco para aqueles que não entendia muito isso.

>>> class MyClass:
...     def myPublicMethod(self):
...             print 'public method'
...     def __myPrivateMethod(self):
...             print 'this is private!!'
... 
>>> obj = MyClass()

O que eu fiz foi criar uma classe com um método público e privado, método e instanciá-lo.

Em seguida, chamar o método público.

>>> obj.myPublicMethod()
public method

Seguinte, eu tento chamar seu método particular.

>>> obj.__myPrivateMethod()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: MyClass instance has no attribute '__myPrivateMethod'

Tudo parece bom aqui;podemos chamá-lo.É, na verdade, de "privado".Bem, de facto não o é.Execução dir() sobre o objeto revela um novo e mágico, o método que o python cria mágica para todos os seus 'privado' métodos.

>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']

Este novo método é sempre um carácter de sublinhado, seguido do nome da classe, seguido do nome do método.

>>> obj._MyClass__myPrivateMethod()
this is private!!

Tanto para o encapsulamento, hein?

Em qualquer caso, eu sempre ouvi dizer que o Python não oferece suporte a encapsulamento, então, por que mesmo tentar?O que dá?

Foi útil?

Solução

O nome de embaralhamento é usado para garantir que subclasses não acidentalmente substituir o privado, métodos e atributos de suas superclasses.Ele não foi concebido para impedir o acesso deliberado de fora.

Por exemplo:

>>> class Foo(object):
...     def __init__(self):
...         self.__baz = 42
...     def foo(self):
...         print self.__baz
...     
>>> class Bar(Foo):
...     def __init__(self):
...         super(Bar, self).__init__()
...         self.__baz = 21
...     def bar(self):
...         print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}

É claro que, se decompõe se a duas classes diferentes têm o mesmo nome.

Outras dicas

Exemplo de função privada

import re
import inspect

class MyClass :

    def __init__(self) :
        pass

    def private_function ( self ) :
        try :
            function_call = inspect.stack()[1][4][0].strip()

            # See if the function_call has "self." in the begining
            matched = re.match( '^self\.', function_call )
            if not matched :
                print 'This is Private Function, Go Away'
                return
        except :
            print 'This is Private Function, Go Away'
            return

        # This is the real Function, only accessible inside class #
        print 'Hey, Welcome in to function'

    def public_function ( self ) :
        # i can call private function from inside the class
        self.private_function()

### End ###

Quando vim pela primeira vez a partir de Java, Python eu odiava isso.Ele me assustou até a morte.

Hoje, ele só poderia ser uma coisa Eu te amo mais sobre o Python.

Eu amo estar em uma plataforma, onde as pessoas confiam umas nas outras e não se sentir como eles precisam para construir impenetrável paredes em torno de seus códigos.No fortemente encapsulado línguas, se uma API tem um erro, e você tem de descobrir o que der errado, você pode ainda não ser possível contornar isso porque o método necessário é privado.Em Python, a atitude é:"com certeza".Se você acha que você compreender a situação, talvez você tenha até mesmo de lê-lo, então tudo o que podemos dizer é "boa sorte!".

Lembre-se, o encapsulamento não é mesmo fracamente relacionadas com "segurança", ou de manter as crianças fora do gramado.É apenas outro padrão que deve ser usado para fazer uma base de código mais fácil de entender.

A partir de http://www.faqs.org/docs/diveintopython/fileinfo_private.html

Estritamente falando, métodos privados são acessíveis fora da classe, apenas não é facilmente acessível.Nada Python é verdadeiramente privada;internamente, os nomes de métodos particulares e atributos são deturpados e unmangled na mosca, para fazê-los parecer inacessível por seus nomes.Você pode aceder a __método de análise do MP3FileInfo classe com o nome _MP3FileInfo__analisar.Reconhecem que isso é interessante, então prometo nunca, nunca fazê-lo no código real.Métodos Private são privados de uma a razão, mas como muitas outras coisas no Python, seus privateness é em última análise, uma questão de convenção, não força.

A frase comumente usada é "somos todos adultos aqui".Por prefixação um único carácter de sublinhado (não exponha) ou sublinhado duplo (ocultar), você está dizendo para o usuário de sua classe que pretende o membro a ser 'privado' de alguma forma.No entanto, você estiver confiante com que todos os outros se comportam de forma responsável e o respeito que, a menos que tenha uma razão muito forte para não (e.g.depuradores, conclusão de código).

Se você realmente deve ter algo que é particular, então você pode implementá-lo em uma extensão (por exemplo,em C para o CPython).Na maioria dos casos, no entanto, você simplesmente aprender a Pythonic maneira de fazer as coisas.

Não é como se você absolutamente não pode ficar em torno de privateness de membros em qualquer língua (aritmética de ponteiro em C++, Reflexões .NET/Java).

O ponto é que você receber um erro se você tentar chamar o método privado por acidente.Mas se você quiser atirar no próprio pé, vá em frente e faça isso.

Editar:Você não tentar garantir que o seu material por OO-encapsulação, não é?

O class.__stuff convenção de nomenclatura permite que o programador sabe que ele não foi criado para acesso __stuff a partir de fora.O nome desconfiguração torna improvável que alguém vai fazer isso por acidente.

É verdade, você ainda pode contornar isto, é até mais fácil do que em outras línguas (que BTW também permite que você faça isso), mas nenhum programador Python iria fazer isso se ele se preocupa com o encapsulamento.

Comportamento semelhante existe quando o módulo de atributo de nomes começam com um único carácter de sublinhado (por exemplo,_foo).

Módulo de atributos chamado como tal não irá ser copiado para um módulo de importação quando utilizar o from* o método, por exemplo:

from bar import *

No entanto, esta é uma convenção e não uma linguagem de restrição.Esses não são atributos privados;eles podem ser referenciados e manipulados por qualquer importador.Alguns argumentam que, devido a isso, o Python não pode implementar verdadeiro encapsulamento.

É apenas um daqueles idioma opções de design.Em algum nível, eles são justificados.Eles fazem isso para que você precisa ir muito longe, fora do seu caminho para tentar chamar o método, e se você realmente precisa que o mal, você deve ter uma boa razão!

A depuração de ganchos e testes vêm à mente como possíveis aplicações, o uso responsável de curso.

Com o Python 3.4 este é o comportamento:

>>> class Foo:
        def __init__(self):
                pass
        def __privateMethod(self):
                return 3
        def invoke(self):
                return self.__privateMethod()


>>> help(Foo)
Help on class Foo in module __main__:

class Foo(builtins.object)
 |  Methods defined here:
 |
 |  __init__(self)
 |
 |  invoke(self)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables (if defined)
 |
 |  __weakref__
 |      list of weak references to the object (if defined)

 >>> f = Foo()
 >>> f.invoke()
 3
 >>> f.__privateMethod()
 Traceback (most recent call last):
   File "<pyshell#47>", line 1, in <module>
     f.__privateMethod()
 AttributeError: 'Foo' object has no attribute '__privateMethod'

https://docs.python.org/3/tutorial/classes.html#tut-private

Observe que a desconfiguração regras são projetados principalmente para evitar acidentes; ainda é possível acessar ou modificar uma variável que é considerado privado. Isso pode até ser útil em circunstâncias especiais, como no depurador.

Mesmo se a questão é antiga, eu espero que o meu trecho poderia ser útil.

A preocupação mais importante sobre o privado, métodos e atributos, é dizer que os desenvolvedores não chamá-lo de fora da classe e este é o encapsulamento.pode-se entender mal de segurança de encapsulamento.quando um deliberadamente usa a sintaxe como que(abaixo) que você mencionou, você não quer que o encapsulamento.

obj._MyClass__myPrivateMethod()

Eu ter migrado a partir do C#, e no começo foi estranho para mim também, mas depois de um tempo me veio a idéia de que apenas a forma que o Python de código designers a pensar sobre OOP é diferente.

Por que Python 'privado' métodos, na verdade, não privada?

Como eu a entendo, eles não pode ser privado.Como poderia privacidade será aplicada?

A resposta óbvia é "membros privados só podem ser acessados através self", mas que não iria funcionar - self não é especial em Python, ele é nada mais do que uma comumente usada nome para o primeiro parâmetro de uma função.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top