Pergunta

Suponha que eu tenho uma classe com alguns atributos. Como é que é melhor (no Pythonic-OOP) sentido para acessar esses atributos? Assim como obj.attr? Ou talvez write obter acessores? Quais são os estilos de nomenclatura aceitos para essas coisas?

Editar: Você pode elaborar sobre as melhores práticas de nomear atributos com um único ou duplo sublinhado à esquerda? Eu vejo na maioria dos módulos que um único sublinhado é usado.


Se esta pergunta já foi feita (e eu tenho um palpite que tem, embora a pesquisa não trouxe resultados), aponte para ele por favor -. E eu vou fechar este

Foi útil?

Solução

A forma geralmente aceite de fazer as coisas é apenas usando atributos simples, como assim

>>> class MyClass:
...     myAttribute = 0
... 
>>> c = MyClass()
>>> c.myAttribute 
0
>>> c.myAttribute = 1
>>> c.myAttribute
1

Se você achar que precisa de ser capaz de getters escrever e setters, então o que você quer procurar é "propriedades da classe python" e o artigo de Ryan Tomayko em Getters / Setters / Fuxors é um ótimo lugar para começar (embora um pouco longo)

Outras dicas

Com relação às sublinhados individuais e duplos-líder: ambos indicam o mesmo conceito de 'caráter privado'. Ou seja, as pessoas vão saber o atributo (seja um método ou um atributo de dados 'normal' ou qualquer outra coisa) não faz parte da API pública do objeto. As pessoas vão saber que para tocá-lo diretamente é um convite ao desastre.

Além disso, os atributos dupla líder sublinhado (mas não os atributos de liderança de um único sublinhado) são nome-mutilado para tornar o acesso a eles por acidente de subclasses ou em qualquer outro lugar fora da classe atual, menos provável. Você ainda pode acessá-los, mas não tão trivial. Por exemplo:

>>> class ClassA:
...     def __init__(self):
...         self._single = "Single"
...         self.__double = "Double"
...     def getSingle(self):
...         return self._single
...     def getDouble(self):
...         return self.__double
... 
>>> class ClassB(ClassA):
...     def getSingle_B(self):
...         return self._single
...     def getDouble_B(self):
...         return self.__double
... 
>>> a = ClassA()
>>> b = ClassB()

Você pode a._single agora trivialmente acesso e b._single e se o atributo _single criado por ClassA:

>>> a._single, b._single
('Single', 'Single')
>>> a.getSingle(), b.getSingle(), b.getSingle_B()
('Single', 'Single', 'Single')

Mas tentando acessar o atributo __double na instância a ou b diretamente não vai funcionar:

>>> a.__double
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: ClassA instance has no attribute '__double'
>>> b.__double
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: ClassB instance has no attribute '__double'

E embora os métodos definidos no ClassA pode chegar a ele diretamente (quando chamado em ambos os casos):

>>> a.getDouble(), b.getDouble()
('Double', 'Double')

Os métodos definidos na ClassB não pode:

>>> b.getDouble_B()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in getDouble_B
AttributeError: ClassB instance has no attribute '_ClassB__double'

E bem nesse erro que você receber uma dica sobre o que está acontecendo. O nome do atributo __double, quando acessado dentro de uma classe, é ser-nome desconfigurado para incluir o nome da classe que está sendo acessado em . Quando tenta ClassA ao acesso self.__double, ele realmente transforma - pelo compiletime - em um acesso de self._ClassA__double, e da mesma forma para ClassB. (Se um método em ClassB foram para atribuir a __double, não incluído no código para a brevidade, não seria mesmos tocar ClassA de __double mas criar um novo atributo.) Não há nenhuma outra proteção deste atributo, assim você ainda pode acessá-lo diretamente se você sabe o nome certo:

>>> a._ClassA__double, b._ClassA__double
('Double', 'Double')

Então, por que este é um problema?

Bem, é um problema qualquer momento você quiser herdar e mudar o comportamento de qualquer negociação código com este atributo. Você quer ter reimplementar tudo o que toca este atributo duplo sublinhado diretamente, ou você tem que adivinhar o nome da classe e mangle o nome manualmente. O problema se agrava quando este atributo duplo sublinhado é na verdade um método: substituindo o método ou chamando o método em uma subclasse significa fazer o nome-desconfiguração manualmente ou reimplementar todo o código que chama o método de não use o nome de duplo sublinhado. Sem mencionar acessando o atributo de forma dinâmica, com getattr():. você terá que manualmente mangle lá, também

Por outro lado, porque o atributo só é trivialmente reescrito, ele oferece apenas 'proteção' superficial. Qualquer pedaço de código ainda pode obter no atributo pelo deturpação manualmente, embora que vai fazer sua dependente o nome de código o classe, e os esforços do seu lado para refatorar seu código ou renomear sua classe (enquanto ainda mantém o mesmo nome visível para o usuário, uma prática comum em Python) seria desnecessariamente quebrar seu código. Eles também podem 'truque' Python em fazer o nome-desconfiguração para eles, nomeando sua classe a mesma que a sua: Observe como não há nenhum nome módulo incluído no nome do atributo mutilado. E, por último, o atributo duplo sublinhado ainda é visível em todas as listas de atributos e todas as formas de introspecção que não tomar cuidado para pular atributos que começam com um sublinhado ( única ).

Assim, se você usar nomes de duplo sublinhado, usá-los excessivamente com moderação, como eles podem revelar-se bastante inconveniente, e nunca usá-los para métodos ou qualquer outra coisa que uma subclasse pode sempre querer reimplementar, substituição ou acesso diretamente . E perceber que double-líder sublinhado-desconfiguração nome ofertas sem proteção real . No final, utilizando um único sublinhado levando você ganha tanto e dá-lhe menos (potencial futuro) dor. Use um único sublinhado líder.

Edit: Você pode elaborar sobre as melhores práticas de nomear atributos com um único ou duplo sublinhado à esquerda? Eu vejo na maioria dos módulos que um único sublinhado é usado.

Single sublinhado não faz especial significa nada para python, é apenas melhores práticas, para dizer "ei, você provavelmente não quer acessar este se você não sabe o que está fazendo". sublinhado duplo no entanto faz python mangle o nome fazendo internamente acessível apenas a partir da classe onde ele está definido.

Double esquerda e à direita sublinhado denota uma função especial, como __add__ que é chamado quando usando o operador +.

Leia mais em PEP 8 , especialmente as "Convenções de nomenclatura" seção.

Eu acho que a maioria só acessá-las diretamente, sem necessidade de métodos get / set.

>>> class myclass:
...     x = 'hello'
...
>>>
>>> class_inst = myclass()
>>> class_inst.x
'hello'
>>> class_inst.x = 'world'
>>> class_inst.x
'world'

BTW, você pode usar a função dir () para ver o que atribui / métodos estão ligados à sua instância:

>>> dir(class_inst)
['__doc__', '__module__', 'x']

Dois líderes barras inferiores, "__" são usados ??para fazer um atributo ou função privada. Para outras convenções referem-se a PEP 08: http://www.python.org/dev/peps/pep-0008/

Python não precisa definir acessores desde o início, uma vez que a conversão de atributos em propriedades é rápido e indolor. Consulte o seguinte para uma demonstração vívida:

recuperação da dependência

Não há nenhum ponto real de fazer getter / setters em python, você não pode coisas proteção de qualquer maneira e se você precisa executar algum código extra quando obter / definir o olhar imóvel no builtin imóvel () (python -c ' ajuda (propriedade) ')

Algumas pessoas usam getters e setters. Dependendo de qual estilo de codificação que você usa, você pode nomeá-los getSpam e seteggs. Mas você também pode fazer você atributos somente leitura ou atribuir somente. Isso é um pouco estranho para fazer. Uma maneira é substituir o

> __getattr__

e

> __setattr__

métodos.

Editar:

Enquanto a minha resposta ainda é verdade, isso não é certo, como eu vim a perceber. Há maneiras melhores de fazer acessores em python e não são muito estranho.

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