Alura > Cursos de Programação > Cursos de Python > Conteúdos de Python > Primeiras aulas do curso Python: aplicando a Orientação a Objetos

Python: aplicando a Orientação a Objetos

Classes - Apresentação

Lais: Boas-vindas a mais um curso de Python! Eu sou Lais Urano e estou aqui, nos estúdios da Alura, com…

Guilherme: Guilherme Lima.

Autodescrição: Lais se considera uma mulher parda, de olhos e cabelos castanhos, cabelos encaracolados. Enquanto o Guilherme usa óculos, tem barba e cabelo curto. Eles estão nos estúdios da Alura, sentado à uma mesa preta, um de frente para o outro. Sobre a mesa, há dois laptops, um mouse sobre um mousepad e dois microfones. A parede ao fundo tem uma iluminação roxa.

Guilherme: Estou muito felizes de ter você neste curso sobre orientação a objetos. Lais, o que vamos aprender neste curso?

Lais: Neste curso, vamos introduzir os conceitos de orientação a objetos, como classe, atributos de instância, métodos e a construtora.

O que vamos aprender:

Guilherme: Além disso, vamos aprender como utilizar os métodos que o Python gera quando criamos uma classe, denominados métodos especiais. Vamos gerar nossos próprios métodos, criar objetos e aprofundar nossos conhecimentos em orientação a objetos, um paradigma muito conhecido e usado no mercado.

Lais: Também vamos aprender a modularizar nossas classes para utilizá-las em outros arquivos.

Guilherme: Esperamos que você goste deste curso. Lembre-se de que temos um fórum do curso e uma comunidade Alura no Discord para fortalecer ainda mais nossos conhecimentos.

Classes - Classes

Lais: Até o momento, estávamos desenvolvendo de um segmento do back-end de um aplicativo chamado Sabor Express, que está, atualmente, realizando o cadastro de restaurantes. Estávamos utilizando funções, métodos e estruturas sequenciais em nosso código. Agora, vamos adentrar um paradigma que utilizamos bastante, o orientado a objetos.

Guilherme: Esse paradigma de orientação a objetos é muito usado no mercado e nos ajudará a garantir um pouco mais como conseguimos lidar com os dados na nossa aplicação. No primeiro curso que desenvolvemos, usamos bastante função. Agora, vamos transportar para um conceito que vamos chamar de objeto, muito conhecido em Python.

Vamos começar o Sabor Express agora com outro paradigma de programação. Vamos criar um arquivo do desde o início, então, no Desktop (Área de tarefas), clicarei com o botão direito do mouse em um espaço vazio e vou selecionar "Nova pasta" no menu. Chamaremos a paste de "oo-sabor-express", e nela manteremos todo o código relacionado ao que desenvolveremos nesse curso.

Agora abriremos o Visual Studio Code e arrastaremos a pasta "oo-sabor-express" para dentro do programa para começarmos a desenvolver. Começaremos criando uma pasta onde manteremos todas as nossas classes.

Para isso, na aba Explorador, que fica no lado esquerdo do VS Code, clicaremos no botão de "Nova Pasta", na parte superior direita da aba. Nomearemos essa pasta como "modelos". Com a pasta "modelos" selecionada, clicaremos no botão "Novo arquivo", que chamaremos de restaurante.py, onde criaremos um modelo de um restaurante. É nesse arquivo que manteremos a nossa classe em Python.

Antes de começarmos a criar uma classe, vamos pensar o que é uma classe em Python. Vamos começar pensando o que é um restaurante na nossa aplicação. Quais são as características que esse restaurante tem?

Lais: Até agora temos o nome do restaurante, a categoria e se ele está ou não ativo, ou seja, o estado daquele restaurante no momento.

Arquivo restaurante.py.

nome
categoria
ativo

Guilherme: No projeto anterior, criamos dicionários com essas informações, ou seja, cada dicionário tinha "nome, categoria e ativo". Mas tem um problema, se quiséssemos criar um novo valor em um dos restaurantes, por exemplo, a quantidade de likes, conseguiríamos fazer isso, mas os outros restaurantes criados não teriam esse valor novo.

A ideia é que, quando falarmos em classe, estamos pensando em uma abstração do mundo real: em um código onde conseguiremos juntar tipos diferentes. Por exemplo, sabemos que o nome é uma string, então podemos escrever como nome = '', porque pode ser qualquer nome de restaurante, assim como a categoria também é uma string, ou seja, categoria = ''. O ativo era um tipo booleano, e falávamos que todo restaurante, quando criamos, queremos que ele seja falso, então ativo = False.

nome = ''
categoria = ''
ativo = False

Mas como conseguimos transformar essas três informações para que eles estejam em qualquer restaurante que formos criar? Para isso, usamos uma palavra reservada do Python, chamada class. Sempre que escrevemos class, estamos criando uma classe no Python, e podemos dar um nome para essa classe.

No caso, essa classe representará um restaurante, então é interessante nomeá-la como Restaurante:, adicionando os dois pontos depois do nome. Em seguida, selecionamos o nome, a categoria e o ativo, e pressionamos a "Barra de Espaço" quatro vezes.

class Restaurante:
    nome = ''
    categoria = ''
    ativo = False

Temos uma classe no Python de um jeito muito simples. Essa classe tem os atributos nome, que será uma string, categoria, que também será uma string, e ativo que será False (Falso). Agora, como criamos um restaurante com base nisso?

Quando temos uma classe e queremos criar um restaurante novo, falamos que estamos instanciando, ou criando, um objeto, sendo que um objeto é a instância de uma classe. Então, para criarmos um restaurante novo, primeiro criaremos uma variável. Por exemplo, criaremos a variável de restaurante_praca, que será igual ao objeto Restaurante().

class Restaurante:
    nome = ''
    categoria = ''
    ativo = False
    
restaurante_praca = Restaurante()

Criamos um Restaurante Praça. Podemos criar outro restaurante, pressionando "Enter" e, na linha abaixo, escrevendo restaurante_pizza = Restaurante().

class Restaurante:
    nome = ''
    categoria = ''
    ativo = False
    
restaurante_praca = Restaurante()
restaurante_pizza = Restaurante()

De agora em diante, qualquer restaurante que quisermos criar, teremos o nome de uma variável, onde vamos armazená-lo, e informaremos que ele será do tipo, Restaurante(). Para visualizarmos esses restaurantes da forma que aparecem no programa, adicionaremos esses dois restaurantes em uma lista chamada restaurantes. Também pediremos um print() nos nossos restaurantes para vê-los.

class Restaurante:
    nome = ''
    categoria = ''
    ativo = False
    
restaurante_praca = Restaurante()
restaurante_pizza = Restaurante()

restaurantes = [restaurante_praca, restaurante_pizza]

print(restaurantes)

Vamos abrir o Terminal para vermos como ficou. Com o Terminal aberto, precisei executar o comando quit(), porque abri o terminal integrado sem querer. Porém, para vermos nossos restaurantes, escreveremos o comando python seguido do endereço do nosso código no VS Code, ou seja, python modelos/restaurante.py. Quando pressionamos "Enter", aparecem duas informações um pouco estranhas, mas não é um erro.

[<__main__.Restaurante object at 0x...>, <__main__.Restaurante object at 0x...>]

Apareceu essa lista onde temos __main__.Restaurante object at seguido de um valor estranho e, depois de uma vírgula, uma informação parecida, mas com outro valor. Por que o Python está mostrando esses valores para nós?

Lais: Ele não está mostrando tantas informações. A única coisa que sabemos é que a informação que ele exibe é um objeto da classe Restaurante. Ele não mostra mais informações ou detalhes, apenas o local da memória onde está armazenado aquele objeto.

Guilherme: Ou seja, não conseguimos ver as informações que queríamos, por exemplo, como definimos o nome ou a categoria de um restaurante que criamos. Então, criamos a classe contendo os atributos que queríamos para ela.

Sempre que pensarmos em uma classe, temos que pensar quais são os atributos, ou seja, as características dessa entidade que queremos criar. Vamos supor que queremos criar uma entidade chamada pessoa, então precisamos pensar nas características de uma pessoa que queremos dentro de um sistema, como o RG e o CPF.

Se quisermos criar uma classe de carros, podemos pensar como características a quantidade de rodas e a cor. Reparem que toda essa abstração que trazemos do mundo real e colocamos no programa, definirá as nossas classes posteriormente.

Depois que criamos a nossa classe, queremos usar essa classe. Para isso, criamos uma variável e passamos o nome da classe, abrindo e fechando parênteses após o nome, ou seja, NomeDaClasse(). Dessa forma, criamos um objeto dessa classe.

Tanto que, quando pedimos para mostrar um print() dos restaurantes, as informações apareceram como restaurante object, um objeto de restaurante armazenado no endereço que aparece depois dele. Esse objeto está na memória, mas não conseguimos ver os outros dados, e é isso que vamos ver no próximo vídeo.

Classes - Atributos de instância

Guilherme: Nós temos agora o desafio de definir o nome, a categoria e o estado ativo para os restaurantes que temos. Começaremos pelo restaurante_praca. Para definirmos um nome para ele, abaixo da linha em branco abaixo dele escreveremos restaurante_praca..

# código omitido

restaurante_praca = Restaurante()
restaurante_praca.
restaurante_pizza = Restaurante()

# código omitido

Ao escrevermos o ponto (.) depois de restaurante_praca, acessamos esse objeto e, dessa forma, ele abre um menu suspenso com várias opções, como ativo, categoria e nome. Selecionaremos a opção nome e atribuiremos o nome 'Praça', como string: restaurante_praca.nome = 'Praça'. E qual será a categoria, Lais?

Lais: A categoria dele será "Gourmet".

Guilherme: Então escrevemos restaurante_praca.categoria = 'Gourmet'. Finalmente, o Restaurante Praça terá com o atributo ativo definido como Falso e manteremos assim, portanto, não precisaremos alterar esse valor. Vamos alterar somente a última linha para visualizarmos apenas o Restaurante Praça, deixando como print(restaurante_praca).

# código omitido

restaurante_praca = Restaurante()
restaurante_praca.nome = 'Praça'
restaurante_praca.categoria = 'Gourmet'

restaurante_pizza = Restaurante()

restaurantes = [restaurante_praca, restaurante_pizza]

print(restaurante_praca)

No Terminal, quando executamos o python modelos/restaurante.py, ainda não conseguimos ver os valores que criamos, apenas o endereço de memória desse objeto. Existe uma maneira de conseguirmos visualizar, pelo menos, algumas informações. O que a classe Restaurante tem como propriedades, atributos e métodos?

Lais: Temos uma função que podemos utilizar, que é a função dir(). Então, ao invés de passarmos o nome da classe no print(), passamos o dir(restaurante_praca), com o nome do objeto, restaurante_praca, como atributos. Vamos descobrir o que o Terminal retorna.

# código omitido

restaurante_praca = Restaurante()
restaurante_praca.nome = 'Praça'
restaurante_praca.categoria = 'Gourmet'

restaurante_pizza = Restaurante()

restaurantes = [restaurante_praca, restaurante_pizza]

print(dir(restaurante_praca))

Guilherme: Ao limparmos o Terminal e executarmos o comando python modelos/restaurante.py novamente, obtemos várias informações dessa vez, entre elas "'ativo', 'categoria' e 'nome', no final da lista, que são os últimos que criamos.

Terminal:

PS C:\Users\nome\Desktop\oo-sabor-express> python modelos/restaurante.py

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'ativo', 'categoria', 'nome']

Mas esse objeto dir() já possui uma série de informações, como __classe__. Sempre que temos esse __ (underline, underline), significa que é um método especial que toda classe em Python possui. Quando faz sentido olhar para o dir()? Principalmente quando se trata de uma classe que não conhecemos.

Quando queremos entender os métodos e como ela funciona, conseguimos visualizar através do retorno do dir(). No entanto, existe outra função que exibirá um dicionário com os atributos dessa classe, similar ao que vimos no nosso curso onde trabalhamos com várias funções.

Portanto, o dir() mostrará tudo: os atributos, métodos e propriedades de um objeto. Quando o substituímos por vars(), queremos um dicionário desses atributos e métodos. Vamos fazer um teste.

Código:

# código omitido

restaurante_praca = Restaurante()
restaurante_praca.nome = 'Praça'
restaurante_praca.categoria = 'Gourmet'

restaurante_pizza = Restaurante()

restaurantes = [restaurante_praca, restaurante_pizza]

print(vars(restaurante_praca))

Terminal:

PS C:\Users\nome\Desktop\oo-sabor-express> python modelos/restaurante.py
{'nome': 'Praça', 'categoria': 'Gourmet'}

Ao executarmos dessa vez, recebemos no formato que tínhamos na função, com o 'nome': 'Praça', 'categoria': 'Gourmet'. Porém o 'ativo' não apareceu.

O ativo está definido para esse restaurante, tanto que, se executarmos o print(restaurante_praca.ativo) e, no Terminal, rodarmos o python modelos/restaurante.py, recebemos o retorno False (Falso). Portanto, o ativo está armazenado, mas ele não listou esse valor para nós.

Temos apenas um pequeno problema. Entendemos como criar uma classe e como definir os valores dessa classe através do ponto (.). A vantagem da classe é que todo objeto restaurante terá um nome e uma categoria, que são os atributos da classe. Mas seria ainda melhor se criássemos a classe e já definíssemos o nome e a categoria do restaurante.

Portanto, é melhor que, ao criarmos uma nova classe, já temos esses métodos. Faremos isso na sequência.

Sobre o curso Python: aplicando a Orientação a Objetos

O curso Python: aplicando a Orientação a Objetos possui 109 minutos de vídeos, em um total de 42 atividades. Gostou? Conheça nossos outros cursos de Python em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Python acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas