Classe Atributos Metamorfoses

Uma breve nota da série "Você foi avisado".

Mudar de linguagens de programação clássicas para Python traz muitas surpresas.
Leia a documentação:
De um modo geral, as variáveis ​​de instância são para dados exclusivos de cada instância e as variáveis ​​de classe são para atributos e métodos compartilhados por todas as instâncias da classe
Vamos tentar brincar

class Vessel: #class attribute vtype = "boat" #instance attribute def __init__(self, name): self.name = name #    def __str__(self): res= '>>' for a in inspect.getmembers( self): if not a[0].startswith("__"): res += f"{a[0]}={a[1]:<14}" for a in inspect.getmembers( self.__class__): if not a[0].startswith("__"): res += f"__class__.{a[0]}={a[1]:<14}" return res 


Crie dois objetos, verifique os valores de todos os atributos:

 Iowa = Vessel("Iowa") Drum=Vessel("Drum") printAttr(Iowa, Drum) >>name=Iowa vtype=boat __class__.vtype=boat >>name=Drum vtype=boat __class__.vtype=boat 

Até agora, como esperado.

Vamos tentar mudar o vtype: isso pode ser feito de duas maneiras, que são essencialmente apenas uma sintaxe diferente da mesma

 Vessel.vtype = "USS boat" printAttr(Iowa, Drum) >>name=Iowa vtype=USS boat __class__.vtype=USS boat >>name=Drum vtype=USS boat __class__.vtype=USS boat Iowa.__class__.vtype = 'USS WW2 Boat' printAttr(Iowa, Drum) >>name=Iowa vtype=USS WW2 Boat __class__.vtype=USS WW2 Boat >>name=Drum vtype=USS WW2 Boat __class__.vtype=USS WW2 Boat 

E, novamente, tudo está em ordem.

Agora vamos tentar fazer o mesmo através do atributo do objeto.

 Drum.vtype = 'submarine' printAttr(Iowa, Drum) >>name=Iowa vtype=USS WW2 Boat __class__.vtype=USS WW2 Boat >>name=Drum vtype=submarine __class__.vtype=USS WW2 Boat 

E aqui está a primeira surpresa: apesar do fato de que vtype é um atributo de uma classe, de repente ele se torna um atributo de um objeto.

Verifique:

 Vessel.vtype = "NAVY Museum" >>name=Iowa vtype=NAVY Museum __class__.vtype=NAVY Museum >>name=Drum vtype=submarine __class__.vtype=NAVY Museum 

e se ...

  del Drum.vtype >>name=Iowa vtype=NAVY Museum __class__.vtype=NAVY Museum >>name=Drum vtype=NAVY Museum __class__.vtype=NAVY Museum 

E novamente um atributo de classe.

A expressão a seguir não passa mais

 del Drum.vtype printAttr(Iowa, Drum) del Drum.vtype AttributeError: vtype 

E o último exemplo que emula a classe substitui e remove o atributo vtype.

 Drum.vtype = 'submarine' del Vessel.vtype printAttr(Iowa, Drum) >>name=Iowa >>name=Drum vtype=submarine 

Se você começar a lidar com o espaço para nome, esse comportamento se tornará compreensível.
No entanto, para programadores que trabalharam anteriormente com linguagens normais, isso pelo menos parece estranho. E se falamos de grandes projetos apoiados por várias gerações de desenvolvedores, isso pode resultar em falha de prazos, etc.

Levando em conta o conceito de Python de que tudo está aberto a todos, por que não acessar os atributos "legais" somente por meio de __class__ ou de seu análogo. Na minha opinião, isso de alguma forma protegeria contra surpresas e me fez pensar 10 vezes antes de atribuir algo aos atributos de classe no nível do objeto.

Atualização: Text PrintAttr

 def printAttr(*o): for a in o: print(a) 

Source: https://habr.com/ru/post/pt427065/


All Articles