Pergunta

Como posso fazer para métodos de membros de dados e o privado em Python?Ou não o suporte ao Python membros privados?

Foi útil?

Solução

9.6.Variáveis Privadas

"Privado" variáveis de instância que não pode ser acessado a partir de dentro, exceto um objeto, não existe em Python.No entanto, há uma convenção que é seguido por mais de Python de código:um nome de prefixado com um carácter de sublinhado (por exemplo,_spam) deve ser tratado como um não-pública parte da API (se é é uma função, um método ou uma data - membro).Deve ser considerado um detalhe de implementação e sujeitos a alteração sem aviso prévio.

Já que não é válido caso de uso para classe-membros privados (nomeadamente para evitar nome conflitos de nomes com nomes definido por subclasses), há suporte limitado para tal mecanismo, chamado de desconfiguração do nome.Qualquer identificador do formulário __spam (pelo menos dois caracteres de sublinhado à esquerda, no máximo, uma sublinhado à direita) é textualmente substituído com _classname__spam, onde o nome da classe é o atual nome da classe com sublinhados(s) removidos.Essa desconfiguração é feito sem levar em conta para a posição sintática do identificador, contanto que ocorre dentro da definição de uma classe.

Assim, por exemplo,

class Test:
    def __private_symbol(self):
        pass
    def normal_symbol(self):
        pass

print dir(Test)

saída:

['_Test__private_symbol', 
'__doc__', 
'__module__', 
'normal_symbol']

__private_symbol deve ser considerado um método particular, mas ele ainda seria acessível através de _Test__private_symbol.

Outras dicas

As outras respostas fornecem os detalhes técnicos. Eu gostaria de enfatizar a diferença de filosofia entre Python, por um lado, e idiomas como C ++/Java (com os quais presumo que você esteja familiarizado com base na sua pergunta).

A atitude geral em Python (e Perl nesse caso) é que a 'privacidade' de um atributo é uma solicitação ao programador, em vez de uma cerca de arame farpado pelo compilador/intérprete. A ideia está bem resumida em este e -mail e é frequentemente referido como "todos somos adultos consentindo", pois 'assume' que o programador é responsável o suficiente para não se intrometer com o interior. Os principais sublinhos servem como uma mensagem educada dizendo que o atributo é interno.

Por outro lado, se você Faz Deseja acessar os internos para alguns aplicativos (um exemplo notável são geradores de documentação como o PYDOC), você é livre para fazê -lo. Onus está em você como um programador para saber o que você está fazendo e fazê -lo corretamente, e não no idioma para forçar que você faz com as coisas Está caminho.

Não há private de qualquer outro mecanismos de proteção de acesso em Python. Há uma convenção documentada no Guia do estilo Python Por indicar aos usuários de sua classe que eles não devem acessar um determinado atributo.

  • _single_leading_underscore: indicador de "uso interno" fraco. Por exemplo from M import * não importa objetos cujo nome começa com um sublinhado.

  • single_trailing_underscore_: usado por convenção para evitar conflitos com a palavra -chave Python, por exemplo Tkinter.Toplevel(master, class_='ClassName')

  • __double_leading_undercore: Ao nomear um atributo de classe, invoca o nome do nome (interno da classe Foobar, __boo se torna _foobar__boo; veja abaixo).

Se o nome de uma função python, método de classe ou atributo começar com (mas não terminar com) dois sublinhados, é privado; Todo o resto é público. O Python não possui conceito de métodos de classe protegidos (acessíveis apenas em suas próprias classes de classe e descendente). Os métodos de classe são privados (acessíveis apenas em sua própria classe) ou públicos (acessíveis de qualquer lugar).

Mergulhe em python

Python não oferece suporte a privacidade diretamente .Programador precisa saber quando é seguro para modificar o atributo de fora, mas de qualquer maneira com python você pode conseguir algo como privado, com pequenos truques.Agora vamos ver uma pessoa pode colocar qualquer coisa privada-lo ou não.

class Person(object):

    def __priva(self):
        print "I am Private"

    def publ(self):
        print " I am public"

    def callpriva(self):
        self.__priva()

Agora, Quando vamos executar :

>>> p = Person()
>>> p.publ()
 I am public
>>> p.__priva()
Traceback (most recent call last):
  File "", line 1, in 
    p.__priva()
AttributeError: 'Person' object has no attribute '__priva'
​#Explanation   : You can see  here we are not able to fetch that private method directly.
>>> p.callpriva()
I am Private
#​Explanation  : Here we can access private method inside class​

Então, como alguém pode acessar essa variável ???
Você pode fazer assim :

>>>p._Person__priva
I am Private

uau , realmente se o python é a obtenção de qualquer variável, começando com duplo sublinhado são "traduzido" pela adição de um único sublinhado e o nome da classe para o início:

Nota : Se você não quiser que essa mudança de nome, mas você ainda quiser enviar um sinal para outros objetos para ficar longe, você pode usar uma única inicial de sublinhado nomes com iniciais de sublinhado não são importados com estrelou importações (do módulo de importação *)
Exemplo :

#test.py
def hello():
    print "hello"
def _hello():
    print "Hello private"

#----------------------
#test2.py
from test import *
print hello()
print _hello()

saída-->

hello
Traceback (most recent call last):
  File "", line 1, in 
NameError: name '_hello' is not defined

Agora, se vamos chamar _hello manualmente .

#test2.py
from test import _hello , hello
print hello()
print _hello()

saída-->

hello
hello private

Finalmente :Python não tem um equivalente de privacidade de apoio, apesar de um único e a dupla inicial, ressalta o fazem, em certa medida, dar-lhe dois níveis de privacidade

Isso pode funcionar:

import sys, functools

def private(member):
    @functools.wraps(member)
    def wrapper(*function_args):
      myself = member.__name__
      caller = sys._getframe(1).f_code.co_name
      if (not caller in dir(function_args[0]) and not caller is myself):
         raise Exception("%s called by %s is private"%(myself,caller))
      return member(*function_args)
    return wrapper

class test:
   def public_method(self):
      print('public method called')

   @private
   def private_method(self):
      print('private method called')

t = test()
t.public_method()
t.private_method()

Essa é uma resposta longa, mas acho que chega à raiz do verdadeiro problema aqui - escopo da visibilidade. Apenas fique lá enquanto eu fico com isso!

Simplesmente importar um módulo não precisa necessariamente dar ao desenvolvedor de aplicativos acesso a todas as suas classes ou métodos; Se eu não consigo ver o código -fonte do módulo, como vou saber o que está disponível? Alguém (ou alguma coisa) tem que me dizer o que posso fazer e explicar como usar esses recursos que posso usar, caso contrário, tudo é inútil para mim.

Aqueles que desenvolvem abstrações de nível superior com base em classes e métodos fundamentais por meio de módulos importados são apresentados com um documento de especificação-não o código-fonte real.

As especificações do módulo descrevem todos os recursos destinados a serem visíveis para o desenvolvedor do cliente. Ao lidar com grandes projetos e equipes de projetos de software, a implementação real de um módulo deve sempre permanecer oculta daqueles que o usam - é uma caixa preta com uma interface para o mundo exterior. Para os puristas de Ood, acredito que os termos técnicos estão "dissocos" e "coerência". O usuário do módulo precisa conhecer apenas os métodos de interface sem ser sobrecarregado com os detalhes da implementação.

Um módulo nunca deve ser alterado sem primeiro alterar seu documento de especificação subjacente, que pode exigir revisão / aprovação em algumas organizações antes de alterar o código.

Como programador de hobby (aposentado agora), inicio um novo módulo com o documento da especificação realmente escrito como um bloco de comentários gigantes na parte superior do módulo, essa será a parte que o usuário realmente vê na biblioteca de especificações. Como sou apenas eu, ainda não tenho uma biblioteca, mas seria fácil de fazer.

Então começo a codificar escrevendo as várias classes e métodos, mas sem corpos funcionais - apenas instruções de impressão nula como "print ()" - apenas o suficiente para permitir que o módulo compilar sem erros de sintaxe. Quando esta etapa é concluída, compilar o módulo nulo concluído-esta é a minha especificação. Se eu estivesse trabalhando em uma equipe de projeto, apresentaria esta especificação/interface para revisão e comentários antes de prosseguir com o corpo.

Recebo os corpos de cada método um de cada vez e compilará de acordo, garantindo que os erros de sintaxe sejam corrigidos imediatamente na fly. Este também é um bom momento para começar a escrever uma seção de execução "principal" temporária na parte inferior para testar cada método ao codificá -lo. Quando a codificação/teste estiver concluída, todo o código de teste é comentado até que você precise novamente as atualizações se tornarem necessárias.

Em uma equipe de desenvolvimento do mundo real, o bloco de comentários da especificação também apareceria em uma biblioteca de controle de documentos, mas isso é outra história. O ponto é: você, como cliente do módulo, veja apenas esta especificação e não o código -fonte.

PS: Muito antes do início dos tempos, trabalhei na comunidade aeroespacial de defesa e fizemos algumas coisas bem legais, mas coisas como algoritmos proprietários e lógica de controle de sistemas sensíveis foram fortemente abobadados e criptografados em bibliotecas de software seguras de super-dupéricas. Tivemos acesso a interfaces de módulo / pacote, mas não aos órgãos de implementação do BlackBox. Havia uma ferramenta de gerenciamento de documentos que lidava com todos os projetos de nível de sistema, especificações de software, código-fonte e registros de teste-tudo foi sincronizado. O governo possuía rigorosos padrões de garantia de qualidade de software. Alguém se lembra de um idioma chamado "Ada"? É quantos anos eu tenho!

Eu uso o Python 2.7 e 3.5. Eu escrevi este código:

class MyOBject(object):
    def __init__(self):
        self.__private_field = 10


my_object = MyOBject()
print(my_object.__private_field)

correu e conseguiu:

AtribuitError: 'myObject' objeto não tem atributo '__private_field'

Por favor, veja:https://www.tutorialsteacher.com/python/private-and-protected-access-modifiers-in-python

Se você deseja tornar os métodos ou membros de dados privados em Python, use __setattr __

class Number:
    def __init__(self,value):
        self.my_private = value

    def __setattr__(self, my_private, value):
        # the default behavior
        # self.__dict__[my_private] = value
        raise Exception("can't access private member-my_private")


def main():
    n = Number(2)
    print(n.my_private)

if __name__ == '__main__': 
    main()
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top