Vamos a algumas definições que permitem o entendimento de classes e objetos:
É como se a classe representasse o conceito e o objeto propriamente dito a concretização da classe.
Considere por exemplo a classe Cachorro, representando um conceito abstrato; e objetos como Rex e Toto, representando a concretização do conceito.
É uma convenção que as classes sejam nomeadas com a primeira letra maiúscula (ex Cachorro). Se o nome for combinado, as primeiras letras de cada palavra seriam maiúsculas, embora a palavra deva ser escritas juntas (CachorroGrande).
Os métodos devem conter o self
se forem se referir à subvariáveis ou métodos da própria classe.
Vejamos um exemplo.
class Cachorro:
# definimos 'subvariáveis'
raca = None # texto descritivo
peso = None # em kg
rabo = None # texto descritivo
cor = None # texto descritivo
temperamento = None # texto descritivo
latido = None # texto a conter 'alto' ou 'baixo'
# definimos um método
def latir(self):
if self.latido == 'alto':
print('AU-AU-AU')
if self.latido=='estridente':
print('rrr-aaau-rrrr-aaau-aaau')
elif self.latido == 'baixo':
print('au-au-au')
Acima criamos uma classe. Agora, vamos concretizar o objeto Rex.
# Criando o Rex
Rex = Cachorro
Rex.raca = 'Pitbull'
Rex.peso = 30
Rex.rabo = 'curto'
Rex.cor = 'preto'
Rex.temperamento = 'manso'
Rex.latido = 'alto'
Rex.latir(Rex) # poderíamos usar Cachorro.latir(Rex)
AU-AU-AU
Objetos podem 'ser sobre-escritos'; na verdade, podendo ser nomes de variáveis possuem o mesmo espaço na memória do computador. Considere o exemplo abaixo.
# Criando o Rex
Rex = Cachorro
Rex.raca = 'Pitbull'
Rex.peso = 30
Rex.rabo = 'curto'
Rex.cor = 'preto'
Rex.temperamento = 'manso'
Rex.latido = 'alto'
Rex.latir(Rex) # poderíamos usar Rex.latir(Rex)
AU-AU-AU
# Criando o Toto
Toto = Cachorro
Toto.raca = 'Pinscher'
Toto.peso = 4
Toto.rabo = 'curto'
Toto.cor = 'preto'
Toto.temperamento = 'demonstra raiva'
Toto.latido = 'estridente'
Toto.latir(Toto) # poderíamos usar Toto.latir(Toto)
rrr-aaau-rrrr-aaau-aaau
# Revendo as propriedades do Rex
print(Rex.raca)
Pinscher
Na verdade, na forma escrita, Rex
e Toto
referenciam-se ao mesmo objeto. Havíamos escrito que Rex
era um Pitbull, mas Toto
passou a ser ma variável que referencia-se ao mesmo objeto; ao mudar Toto
, mudamos Rex
. Podemos verificar isto com o comando is
. O comando O is
compara a identidade do objeto, isto é, o valor de referência de seu endereço na memória (Alura).
Rex is Toto
True
É mais ou menos como a figura do Homem Aranha abaixo.
Para evitar a 'sobreposição de dados' e criar objetos particularizados, podemos usar o comando __init__
com atribuição de dados específicos ao criarmos objetos gerados a partir de classes; com a obrigatoriedade de informar pelo menos um valor particularizado para o objeto. O self
refere-se ao próprio objeto e deve estar sempre presente. Vejamos um exemplo.
class Cachorro2:
def __init__(self,raca,peso,rabo,cor,temperamento,latido):
# definimos 'subvariáveis'
self.raca = raca # texto descritivo
self.peso = peso # em kg
self.rabo = rabo # texto descritivo
self.cor = cor # texto descritivo
self.temperamento = temperamento # texto descritivo
self.latido = latido # texto a conter 'alto' ou 'baixo'
# definimos um método
def latir(self):
if self.latido == 'alto':
print('AU-AU-AU')
if self.latido=='estridente':
print('rrr-aaau-rrrr-aaau-aaau')
elif self.latido == 'baixo':
print('au-au-au')
return(None)
# Criando a Mel (nome da cachorra)
Mel = Cachorro2('Shihtzu',5,'longo','branca e cinza','mansa','baixo')
Cachorro2.latir(Mel)
# Criando a Safira (nome da cachorra)
Safira = Cachorro2('Safira',20,'longo','marrom','brava','alto')
Cachorro2.latir(Safira)
# imprimindo a raça da Mel
print(Mel.raca)
au-au-au AU-AU-AU Shihtzu
Agora sim, os objetos ficaram particularizados!!
Para que os objetos fiquem particularizados, pelo menos uma informação deve ser dada. Por exemplo, a raca
abaixo escrita pode ser informada para ser atribuída, e os demais podem permanecer sem informação. Se não for informada nenhuma variável específica, os objetos podem ser sobrepostos.
class Cachorro3:
def __init__(self,raca):
# definimos 'subvariáveis'
self.raca =raca # texto descritivo
self.peso = None # em kg
self.rabo = None # texto descritivo
self.cor = None # texto descritivo
self.temperamento = None # texto descritivo
self.latido = None # texto a conter 'alto' ou 'baixo'
# definimos um método
def latir(self):
if self.latido == 'alto':
print('AU-AU-AU')
if self.latido=='estridente':
print('rrr-aaau-rrrr-aaau-aaau')
elif self.latido == 'baixo':
print('au-au-au')
return(None)
# Cria o cachorro SAS com um viralatas (Srd atualmente)
Sas = Cachorro3('Srd')
Sas.peso = 17 # Define o peso do cachorro Sas
Sas.latido='alto' # Define o tipo de latido do cachorro Sas
# Cria o cachorro duque
Duque = Cachorro3('Pequenes')
Duque.peso = 5 # Define o peso do cachorro Duque
Duque.latido='baixo' # Define o tipo de latido do cachorro Duque
Note que, no código acima, informamos a raca
pelo método __init__
. O peso foi informado posteriormente. Contudo, o peso do cachorro Sas
foi preservado, conforme pode ser visto abaixo.
print(Sas.peso)
17
Observe que o objeto Sas
é diferente do objeto Duque
, conforme segue.
Sas is Duque
False
Os métodos podem então ser acionados conforme abaixo.
# Latido da SAS
Sas.latir() # acionando por Sas
Cachorro3.latir(Sas) # acionando por Cachorro3
# Latido do Duque
Duque.latir() # acionando por Duque
Cachorro3.latir(Duque) # acionando por Cachorro3
AU-AU-AU AU-AU-AU au-au-au au-au-au
A partir de uma classe 'Pai', podemos criar uma classe 'Filho', que herda todas as propriedades da classe 'Pai'. Por exemplo.
# Classe 'Pai'
class Reator:
tipo = None
volume = None
cor_ent = None
cor_sai = None
reacoes = None
caracteristica = None
# Classe 'Filho'
class ReatorPFR(Reator):
# Define um método para a classe filho
def __init__(self,nome):
self.nome=nome
self.tipo = "PFR"
self.fluxo = "empistonado"
# Classe 'Filho'
class ReatorCSTR(Reator):
# Define um método para a classe filho
def __init__(self,nome):
self.nome=nome
self.tipo = "CSTR"
self.fluxo = "mistura perfeita"
# Define os reatores Reat1 e Reat2
Reat1 = ReatorPFR('Reator 1')
Reat2 = ReatorCSTR('Reator 2')
# Imprime propriedades dos reatores
print([Reat1.nome,Reat1.tipo,Reat1.fluxo])
print([Reat2.nome,Reat2.tipo,Reat2.fluxo])
['Reator 1', 'PFR', 'empistonado'] ['Reator 2', 'CSTR', 'mistura perfeita']
Se as classes Pai e Filho tiverem ambas os métodos __init__
, os objetos criados a partir da classe Filho terão como __init__
(apenas) apenas o que foi definido na classe Filho. Contudo, a classe filho consegue acessar o init
da classe Pai com o comando __super__
. Vejamos um exemplo.
# Classe 'Pai', equipamento
class Equipamento:
Volume = None
def __init__(self,TAG):
self.TAG = TAG
# Classe 'Filho'
class Coluna(Equipamento):
# Define um método para a classe filho
def __init__(self,TAG,Diametro,Altura):
super().__init__(TAG) # aciona a função de inicilização da classe Pai
self.D = Diametro # define o diâmetro
self.H = Altura # define a altura
# Cria o objeto Col1, chamado C1, com diâmetro 2 e altura 7
Col1 = Coluna('C1',2,7)
# Imprime propriedades das colunas
print([Col1.TAG,Col1.D,Col1.H])
['C1', 2, 7]
Há muito mais o que ser falado sobre classes. Contudo, será desenvolvido ao longo do material.