Pergunta

Estou vindo do mundo Java e ler Bruce Eckels' Python 3 padrões, Receitas e idiomas .

Ao ler sobre as aulas, ele continua a dizer que, em Python, não há necessidade de variáveis ??de instância declare. Você só usá-los no construtor, e boom, eles estão lá.

Assim, por exemplo:

class Simple:
    def __init__(self, s):
        print("inside the simple constructor")
        self.s = s

    def show(self):
        print(self.s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

Se isso for verdade, então qualquer objeto de Simple classe pode apenas mudar o valor do lado de fora s variável da classe.

Por exemplo:

if __name__ == "__main__":
    x = Simple("constructor argument")
    x.s = "test15" # this changes the value
    x.show()
    x.showMsg("A message")

Em Java, nós fomos ensinados sobre / variáveis ??privadas / públicas protegidas. Essas palavras-chave faz sentido, porque às vezes você quer variáveis ??em uma classe à qual ninguém fora da classe tem acesso.

Por que é que não é necessário em Python?

Foi útil?

Solução

É cultural. Em Python, você não escreve a instância ou classe variáveis ??de outras classes. Em Java, nada o impede de fazer o mesmo se você realmente quiser - afinal, você sempre pode editar a origem da própria classe para atingir o mesmo efeito. Python cai que pretensão de segurança e incentiva programadores a ser responsável. Na prática, isso funciona muito bem.

Se você quiser emular variáveis ??privadas, por algum motivo, você sempre pode usar o prefixo __ de PEP 8 . Python mangles os nomes de variáveis ??como __foo para que eles não são facilmente visíveis para o código fora da classe que eles (contém embora você pode contorná-la, se você está determinado o suficiente, assim como você pode contornar as proteções de Java, se você trabalhar com ele).

Pela mesma convenção, os meios _ prefixo estadia longe, mesmo se você não está tecnicamente impedidos de fazê-lo . Você não brincar com variáveis ??de outra classe que se parecem com __foo ou _bar.

Outras dicas

variáveis ??privadas em python é mais ou menos um hack:. O intérprete renomeia intencionalmente a variável

class A:
    def __init__(self):
        self.__var = 123
    def printVar(self):
        print self.__var

Agora, se você tentar acessar __var fora da definição de classe, ele irá falhar:

 >>>x = A()
 >>>x.__var # this will return error: "A has no attribute __var"

 >>>x.printVar() # this gives back 123

Mas você pode facilmente ir longe com isso:

 >>>x.__dict__ # this will show everything that is contained in object x
               # which in this case is something like {'_A__var' : 123}

 >>>x._A__var = 456 # you now know the masked name of private variables
 >>>x.printVar() # this gives back 456

Você provavelmente sabe que os métodos em OOP são invocados como este: x.printVar() => A.printVar(x), se A.printVar() pode acessar algum campo em x, este campo também pode ser acessado fora A.printVar() ... afinal de contas, as funções são criadas para reutilização, não há nenhum poder especial dada aos comandos dentro.

O jogo é diferente quando existe um compilador envolvidos ( privacidade é um conceito nível compilador ). Ele sabe sobre definição de classe com modificadores de controle de acesso para que ele possa erro se as regras não estão sendo seguidos em tempo de compilação

Como correctamente mencionado por muitos dos comentários acima, não vamos esquecer o objetivo principal de modificadores de acesso: usuários para ajudar de código de entender o que é suposto mudança e que é suposto não. Quando você vê um campo particular que você não mexer com ele. Portanto, é principalmente açúcar sintático que é facilmente alcançada em Python pela _ e __.

"Em java, nós fomos ensinados sobre públicas / privadas variáveis ??/ protegidas"

"Por que é que não é necessário em python?"

Pela mesma razão, não é necessário em Java.

Você é livre para usar -. Ou não usar private e protected

Como Python e programador Java, eu descobri que private e protected são conceitos de design muito, muito importantes. Mas, como uma questão prática, em dezenas de milhares de linhas de Java e Python, eu nunca realmente private ou protected usado.

Por que não?

Aqui está a minha pergunta "protegido contra quem?"

Outros programadores do meu time? Eles têm a fonte. O que faz protegido média quando eles podem mudar isso?

Outros programadores em outras equipes? Eles trabalham para a mesma empresa. Eles podem - com um telefonema -. Começar a fonte

clientes? É um trabalho de aluguel de programação (em geral). Os clientes (em geral) possuem o código.

Assim, quem - precisamente -? Eu estou protegendo-a de

Há uma variação de variáveis ??privadas na convenção sublinhado.

In [5]: class Test(object):
   ...:     def __private_method(self):
   ...:         return "Boo"
   ...:     def public_method(self):
   ...:         return self.__private_method()
   ...:     

In [6]: x = Test()

In [7]: x.public_method()
Out[7]: 'Boo'

In [8]: x.__private_method()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-fa17ce05d8bc> in <module>()
----> 1 x.__private_method()

AttributeError: 'Test' object has no attribute '__private_method'

Existem algumas diferenças sutis, mas por uma questão de programação padrão de pureza ideológica, é bom o suficiente.

Há exemplos lá fora, de decoradores @private que implementam mais de perto o conceito, mas YMMV. Indiscutivelmente um também poderia escrever um defintion classe que usa meta

Python tem suporte limitado a identificadores privados, através de um recurso que prepends automaticamente o nome de classe para qualquer identificadores começando com dois sublinhados. Este é transparente para o programador, em sua maior parte, mas o efeito líquido é que todas as variáveis ??nomeadas desta forma podem ser usados ??como variáveis ??privadas.

aqui para saber mais sobre isso.

Em geral, a implementação da orientação a objetos do Python é um pouco primitivo em comparação com outras línguas. Mas eu gosto disso, na verdade. É uma implementação e se encaixa muito conceitualmente simples bem com o estilo dinâmico da língua.

Como mencionado anteriormente, você pode indicar que uma variável ou método é privado pré-fixando com um sublinhado. Se você não se sentir como este é o suficiente, você sempre pode usar o decorador property. Aqui está um exemplo:

class Foo:

    def __init__(self, bar):
        self._bar = bar

    @property
    def bar(self):
        """Getter for '_bar'."""
        return self._bar

Desta forma, alguém ou algo que as referências bar está realmente fazendo referência o valor de retorno da função bar em vez da própria variável, e, portanto, ele pode ser acessado, mas não mudou. No entanto, se alguém realmente queria, eles poderiam simplesmente usar _bar e atribuir um novo valor a ela. Não há nenhuma maneira infalível de impedir alguém de variáveis ??e métodos que acessam que você deseja esconder, como tem sido dito repetidamente. No entanto, usando property é a mensagem mais clara você pode enviar que uma variável não está a ser editado. property também pode ser usado para mais complexos caminhos getter / setter / acesso deleter, como explicado aqui: https://docs.python.org/3/library/functions.html#property

A única vez que eu usar variáveis ??privadas é quando eu preciso fazer outras coisas ao escrever ou ler a variável e, como tal necessidade I para forçar o uso de um setter e / ou getter.

Novamente, isto vai para a cultura, como já foi dito. Eu tenho trabalhado em projectos onde a leitura e gravação de variáveis ??de outras aulas foi free-for-all. Quando uma implementação tornou-se obsoleto levou muito mais tempo para identificar todos os caminhos de código que usaram essa função. Quando o uso de setters e getters foi forçado, uma declaração de depuração poderia facilmente ser escrito para identificar que o método obsoleto tinha sido chamado e o caminho de código que o chama.

Quando você está em um projeto onde qualquer um pode escrever uma extensão, notificando os usuários sobre os métodos obsoletos que estão a desaparecer em poucos lançamentos, portanto, é vital para manter a quebra módulo no mínimo sobre as atualizações.

Assim, a minha resposta é; Se você e seus colegas manter um conjunto de códigos simples, em seguida, proteger variáveis ??de classe nem sempre é necessário. Se você estiver escrevendo um sistema extensível, em seguida, torna-se imperativo quando mudanças no núcleo é feito que precisa ser pego por todas as extensões usando o código.

conceitos particulares e protegidas são muito importantes. Mas python - apenas uma ferramenta para prototipagem e desenvolvimento rápido com recursos restritos disponíveis para o desenvolvimento, é por isso que alguns dos níveis de proteção não são tão rigorosas seguida em python. Você pode usar "__" em membro da classe, ele funciona corretamente, mas a aparência não é bom o suficiente - cada acesso a esse campo contém esses caracteres.

Além disso, você pode notado que conceito python OOP não é perfeito, smaltalk ou rubi muito mais perto de conceito OOP puro. Mesmo C # ou Java estão mais próximos.

Python é muito boa ferramenta. Mas é linguagem OOP simplificado. Sintaticamente e conceitualmente simplificada. O principal objetivo da existência python é trazer para desenvolvedores possibilidade de escrever código legível fácil com alto nível de abstração de uma maneira muito rápida.

Indivíduos pesarosos para "ressuscitar" o fio, mas, espero que isso vai ajudar alguém:

Em Python3 se você só quer "encapsular" os atributos de classe, como em Java, você pode simplesmente fazer a mesma coisa como isto:

class Simple:
    def __init__(self, str):
        print("inside the simple constructor")
        self.__s = str

    def show(self):
        print(self.__s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

Para instanciar fazei isto:

ss = Simple("lol")
ss.show()

Note que:. print(ss.__s) irá lançar um erro

Na prática, Python3 irá ofuscar o nome do atributo global. Transformando este como um atributo de "privado", como em Java. O nome do atributo ainda é global, mas de uma forma inacessíveis, como um atributo privado em outros idiomas.

Mas não tenha medo dele. Não importa. Ele faz o trabalho também. ;)

Python não tem nenhum variáveis ??privadas como C ++ ou Java faz. Você pode acessar qualquer variável de membro a qualquer momento se quisesse, também. No entanto, você não precisa de variáveis ??privadas em Python, porque em Python não é ruim para expor suas variáveis ??aulas membros. Se você tiver a necessidade de encapsular uma variável de membro, você pode fazer isso usando "@property", mais tarde, sem quebrar o código do cliente existente.

Em python o único sublinhado "_" é usado para indicar que um método ou variável não é considerado como parte da API pública de uma classe e que esta parte da API pode mudar entre as versões diferentes. Você pode usar estes métodos / variáveis, mas seu código poderia quebrar, se você usar uma versão mais recente desta classe.

O duplo sublinhado "__" não significa uma "variável privada". Você usá-lo para definir variáveis ??que são "classe local" e que não podem ser facilmente overidden por subclasses. Ele mutila o nome variáveis.

Por exemplo:

class A(object):
    def __init__(self):
        self.__foobar = None # will be automatically mangled to self._A__foobar

class B(A):
    def __init__(self):
        self.__foobar = 1 # will be automatically mangled to self._B__foobar
nome

self .__ do foobar é automaticamente mutilado para self._A__foobar na classe A. Na classe B é mutilado para self._B__foobar. Assim, cada subclasse pode definir o seu próprio __foobar variável sem substituir sua variável pais (s). Mas nada o impede de variáveis ??que acessam começando com sublinhados duplos. No entanto,-desconfiguração nome impede de chamar estas variáveis ??/ métodos aliás.

Eu recomendo fortemente para assistir Raymond Hettingers talk "Pythons desenvolvimento de classe kit de ferramentas" de PyCon 2013 (deve estar disponível no Youtube), o que dá um bom exemplo por que e como você deve usar @property e "__" - variáveis ??de instância <. / p>

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