Classe" Private " (implementation) em Python

estou a codificar um pequeno módulo Python composto por duas partes:

    Algumas funções que definem uma interface pública,
  • Uma classe de implementação usada pelas funções acima, mas que não tem significado fora do módulo.

no início, decidi "esconder" esta classe de implementação definindo-a dentro da função que a utiliza, mas isso dificulta a legibilidade e não pode ser usado se várias funções reutilizarem a mesma classe.

assim, para além dos comentários e docstrings, existe um mecanismo para marcar uma classe como "privada"ou " interna"? Estou ciente do mecanismo de underscore, mas, pelo que sei, só se aplica a variáveis, funções e nomes de métodos.

Author: 200_success, 2009-02-15

7 answers

Utilize um único prefixo sublinhado:

class _Internal:
    ...

Esta é a convenção em Python oficial para os símbolos' internos'; "a partir da importação do módulo *" não importa os objectos com prefixos 'underscore'.

Editar: referência à Convenção sobre o sublinhado único

 134
Author: Ferdinand Beyer, 2016-11-11 00:06:56

Em resumo:

  1. Você não pode impor a privacidade . Não existem classes/métodos/funções privadas em Python. Pelo menos, não Privacidade estrita como em outras linguagens, como Java.

  2. Você só pode indicar / sugerir Privacidade. Isto segue uma convenção. A Convenção python para marcar uma classe / função / método como privado é prefaciá-lo com um _ (sublinhado). Por exemplo, def _myfunc() ou class _MyClass:. Você também pode criar pseudo-privacidade ao pré-configurar o método com dois sublinhados (por exemplo: __foo). Você não pode acessar o método diretamente, mas você ainda pode chamá-lo através de um prefixo especial usando o nome da classe (eg: _classname__foo). Então o melhor que você pode fazer é indicar/sugerir privacidade, não aplicá-la.

O Python é como o perl a este respeito. Parafraseando uma famosa linha sobre a privacidade do livro Perl, a filosofia é que você deve ficar fora da sala porque você não foi convidado, não porque é defendido com um espingarda.

Para mais informações:

  • variáveis privadas documentação em Python
  • funções privadas mergulhe em Python, por Mark Pilgrim
  • Porque é que os métodos 'privados' do Python não são realmente privados? pergunta 70528 do StackOverflow
 53
Author: Karl Fast, 2018-06-21 13:49:50

Defina __all__, uma lista de nomes que deseja exportar (veja a documentação).

__all__ = ['public_class'] # don't add here the 'implementation_class'
 35
Author: UncleZeiv, 2009-02-15 15:36:03

Um padrão que às vezes uso é este:

Define uma classe:

class x(object):
    def doThis(self):
        ...
    def doThat(self):
        ...

Criar uma instância da classe, sobrepondo o nome da classe:

x = x()

Defina símbolos que exponham a funcionalidade:

doThis = x.doThis
doThat = x.doThat

Apague a instância em si:

del x
Agora tem um módulo que só expõe as suas funções públicas.
 9
Author: theller, 2009-02-15 15:58:49

A Convenção é preparar " _ " para classes, funções e variáveis internas.

 7
Author: Benjamin Peterson, 2009-02-15 15:33:48

Para abordar a questão das Convenções de design, e como Christopher disse, realmente não existe tal coisa como "privado" em Python. Isto pode parecer retorcido para alguém que vem de fundo C / C++ (como eu há algum tempo atrás), mas, eventualmente, você provavelmente vai perceber que seguir convenções é bastante.

Ver algo com um sublinhado à frente deve ser uma boa dica para não o usar directamente. Se você está preocupado com a bagunça {[[0]} saída (que é o que todos olham para ao pesquisar sobre como usar uma classe), os atributos/classes sublinhados não estão incluídos lá, então você vai acabar tendo apenas a sua interface" pública " descrita.

Além disso, ter tudo público tem as suas próprias vantagens incríveis, como por exemplo, você pode testar a unidade praticamente qualquer coisa de fora (o que você realmente não pode fazer com C/C++ construções privadas).

 4
Author: Dimitri Tcaciuc, 2009-02-15 18:09:59

Usar dois sublinhados para prefixar nomes de identificadores "privados". Para as classes de um módulo, use um único underscore líder e elas não serão importadas usando "from module import *".

class _MyInternalClass:
    def __my_private_method:
        pass

(não existe tal coisa como verdadeiro "privado" em Python. Por exemplo, o Python apenas corrompe automaticamente os nomes dos membros da classe com subcores duplos a serem __clssname_mymember. Então, realmente, se você sabe o nome mutilado você pode usar a entidade "privada" de qualquer maneira. Veja aqui.E claro que podes. escolha importar manualmente as classes "internas"se quiser).

 2
Author: chroder, 2009-02-15 19:59:45