Primeiras aulas do curso Python 3: Avançando na orientação a objetos

Python 3: Avançando na orientação a objetos

Relembrando classes e objetos - Introdução

Olá! Esta é a continuação do curso de Orientação a Objetos com Python. Nosso objetivo será reforçar o conhecimento sobre esse assunto, falaremos sobre alguns aspectos idiomáticos da linguagem, que nos auxiliarão a atuar com Python. Além disso, trataremos aspectos específicos da Orientação a Objeto e como eles são aplicados nesta linguagem.

Por exemplo, herança, polimorfismo e Duck Typing. Falaremos também sobre herança múltipla, um aspecto que pode assustar algumas pessoas, mas apresentaremos de forma sucinta, deixando claro o conceito.

Abordaremos o assunto mixin, falaremos de forma a garantir maior segurança quando trabalharmos com um código Python. Outra situação que podemos encontrar será o código no qual seja exigida uma interface mais ligada aos aspectos desta linguagem.

Tentaremos introduzir esse conhecimento para a linguagem Pyhton ligado a O.O., um tema que este será o foco nesta parte, mas que provavelmente será abordado em outros cursos.

Espero que você goste, vamos praticar bastante!

Relembrando classes e objetos - Relembrando classes e objetos

Começaremos o curso abordando o nosso primeiro assunto, no qual relembraremos classes e objetos. Nós pensaremos em trechos de uma aplicação para absorver melhor esses conceitos de O.O. no Python e tentar entendê-los de uma forma mais tranquila.

Primeiramente lidaremos com este trecho de aplicação, com a qual teremos o controle de playlist de programa de TV. Podemos lidar com filmes, séries, documentários e afins. Começaremos pelo filme - cujo modelo faremos no Python.

Um filme tem as seguintes características:

Uma série, por sua vez, possui:

A partir dessas informações, tentaremos construir um modelo usando a linguagem Python. Para isto, abriremos o PyCharm e criaremos um projeto que receberá o nome python3oo2. Com o número 2 indicamos que é um arquivo referente à segunda parte do curso de O.O..

No interpretador, deixaremos o arquivo configurado com "Python 3.6", por ele já estar instalado na máquina. Em seguida, criaremos o arquivo Modelo.py, nome geralmente usado ao criarmos conceitos de classe os quais representarão um domínio no nosso sistema. Criados o projeto e o modelo, começaremos a trabalhar com o código.

Inicialmente, adicionaremos class Filme - o que precisaremos fazer para criar uma classe? Podemos definir o que será necessário para criar um objeto deste tipo, e teríamos que começar do inicializador. Isso é necessário sempre?

O Python possui uma flexibilidade, que permite que criemos um objeto ao colocarmos pass e indicarmos que simplesmente estamos passando-o. Por exemplo, trabalharemos com o filme vingadores, em seguida verificaremos se o objeto está pronto, com print().

class Filme:

    pass

vingadores = Filme()
print(vingadores)

Até o momento, vingadores não possui um atributo, a ideia é simplesmente demonstrar que conseguimos criar um objeto de uma classe de forma muito flexível. Se clicarmos com o botão direito e selecionarmos "Run 'modelo'", o PyCharm vai imprimir no console as informações, algumas da memória do Python:

C:\Users\Alura\Appdata\Local\Progrms\Python\Python36-32\pythosn.exe\luan.silva
<_mains_.Filme object at 0x050220F0>

Process finished with code 0

Assim, são exibidas as informações correspondentes ao tentarmos imprimir um objeto que seja do tipo filme. Agora vamos modelar essa classe, que na verdade não possui apenas pass, e sim atributos como def, com o qual definiremos o inicializador ( __init__):

class Filme:
    def __init__(self, nome, ano, duracao):
        self.nome = nome
        self.ano = ano
        self.duracao = duracao

vingadores = Filme()
print(vingadores.nome)

O inicializador __init__ sempre receberá self, e também passaremos outros atributos: nome, ano e duracao. Com estes três devemos preencher os três valores do objeto na nossa instancia. Por isso usamos self.nome, self.ano e self.duracao. A partir de agora podemos pedir para que se imprima especificamente o nome do filme, passando para print o vingadores.nome.

Se executarmos novamente o modelo, veremos uma mensagem de erro: TypeError: __init__() missing 3 required positional arguments - fomos avisados de que temos um inicializador com mais argumentos, e que faltou passá-los no código.

vingadores = Filme('vingadores - guerra infinita', 2018, 160)
print(vingadores.nome)

Se executarmos novamente com "Run 'modelo'", veremos impresso:

vingadores - guerra infinita

Em seguida, incluiremos class Serie, podendo-se inclusive aproveitar o código da primeira.

class Filme:
    def __init__(self, nome, ano, duracao):
        self.nome = nome
        self.ano = ano
        self.duracao = duracao

class Serie:
    def __init__(self, nome, ano, temporadas):
        self.nome = nome
        self.ano = ano
        self.temporadas = temporadas

vingadores = Filme('vingadores - guerra infinita', 2018, 160)
print(vingadores.nome)

atlanta = Serie('atlanta', 2018, 2)

print(f'Nome: {atlanta.nome} - Ano: {atlanta.ano} - Temporadas: {atlanta.temporadas}')

Passaremos como série atlanta, isto é, será igual a Serie(), com os valores correspondentes em relação aos atributos nome, ano e temporadas. No caso, ela tem o total de 2 temporadas, e imprimiremos além do nome, a anotação de formatação do Python 3.6. Dentro de {} incluiremos o atributo que queremos imprimir. Observe que, desta vez, adicionamos outras informações na string.

Ao executarmos o código, veremos impresso no console:

vingadores - guerra infinita
Nome: atlanta - Ano: 2018 - Temporadas: 2

Vamos tornar esse informação mais compreensível agregando mais informações em Filme.

class Filme:
    def __init__(self, nome, ano, duracao):
        self.nome = nome
        self.ano = ano
        self.duracao = duracao

class Serie:
    def __init__(self, nome, ano, temporadas):
        self.nome = nome
        self.ano = ano
        self.temporadas = temporadas

vingadores = Filme('vingadores - guerra infinita', 2018, 160)
print(f'Nome: {vingadores.nome} - Ano: {vingadores.ano} ' - 
f'- Duração: {vingadores.duracao}')

atlanta = Serie('atlanta', 2018, 2)

print(f'Nome: {atlanta.nome} - Ano: {atlanta.ano} ' - 
f'- Temporadas: {atlanta.temporadas}')

A impressão ficará da seguinte maneira:

Nome: vingadores - guerra infinita - Ano: 2018 - Duração: 160
Nome: atlanta - ano: 2018 - Temporadas: 2

Relembrando como é criar uma classe e um objeto da mesma... Para onde isso nos leva?

Por enquanto temos nossa aplicação funcionando, mas é normal termos que lidar com informações novas. As aplicações mudam, é normal. No caso, temos uma informação nova: além das informações já disponibilizadas, teremos a quantidade de likes. Será necessário implementarmos uma funcionalidade que indique a popularidade daquela série.

Teremos também uma regra que nos dirá que, sempre que for um filme for inserido, colocaremos um nome específico. No momento em que imprimirmos filme.nome, devemos fazê-lo de forma que Meu Filme esteja com as primeiras letras em maiúsculo.

Nós ainda estamos imprimindo meu filme de forma diferente, mas foi algo dentro do código que conseguiu exibir o texto da forma modificada. Falta implementarmos esta regra de negócio tanto para filmes como para séries.

Vemos que já temos código para fazer, essa será nossa missão a seguir. Mas antes, recomendo que você faça os exercícios de fixação dos conceitos vistos até agora.

Relembrando classes e objetos - Adicionando atributos e métodos

Vamos continuar a escrever os trechos de código referentes a Filme e Serie. Falamos anteriormente que acrescentaríamos algumas regras: ambos os tipos devem informar a quantidade de likes recebida, ou seja, eles passarão a ideia de sua popularidade para a classe.

Outro ponto será a inclusão de um comportamento ao exibirmos um nome de determinada maneira, quando criarmos um objeto do tipo Filme, ao incluirmos meu filme ou meu nome e o colocarmos em nome. Quando passarmos esse elemento pelo inicializador, imprimiremos um nome e este será exibido com as primeiras letras de cada palavra em maiúsculo como em Meu Filme. O mesmo deverá acontecer em relação às séries.

Resolveremos essa questão trabalhando no código, de volta à IDE:

class Filme:
    def __init__(self, nome, ano, duracao):
        self.nome = nome
        self.ano = ano
        self.duracao = duracao


class Serie:
    def __init__(self, nome, ano, temporadas):
        self.nome = nome
        self.ano = ano
        self.temporadas = temporadas


vingadores = Filme('vingadores - guerra infinita', 2018, 160)
print(f'Nome: {vingadores.nome} - Ano: {vingadores.ano} '
f'- Duração: {vingadores.duracao}')

atlanta = Serie('atlanta', 2018, 2)

print(f'Nome: {atlanta.nome} - Ano: {atlanta.ano} '
f'- Temporadas: {atlanta.temporadas}')

O próximo passo será incluir a informação do nome e depois, transformá-lo. Como podemos fazer isso? Investigaremos como funciona a biblioteca de string do Python. Começaremos experimentando a função capitalize() para vermos como isso irá refletir no momento da impressão.

class Filme:
    def __init__(self, nome, ano, duracao):
        self.nome = nome.capitalize()
        self.ano = ano
        self.duracao = duracao

No console, o nome do filme será impresso da seguinte forma:

Nome: Vingadores - guerra infinita - Ano: 2018 - Duração: 160
Nome: atlanta - ano: 2018 - Temporadas: 2

A primeira letra do nome já foi impressa em maiúsculo, mas as demais não. Ao incluirmos capitalize(), podemos "capitalizar" a primeira letra para deixá-la em caixa alta, mas ainda não é bem o que queremos. Vamos testar outra função, title(), e ver se conseguimos modificar o comportamento. Faremos o mesmo na série.

class Filme:
    def __init__(self, nome, ano, duracao):
        self.nome = nome.title()
        self.ano = ano
        self.duracao = duracao

class Serie:
    def __init__(self, nome, ano, temporadas):
        self.nome = nome.title()
        self.ano = ano
        self.temporadas = temporadas

Com o uso do title() teremos o resultado esperado:

Nome: Vingadores - Guerra Infinita - Ano: 2018 - Duração: 160
Nome: Atlanta - ano: 2018 - Temporadas: 2

Agora falta implementar os likes. Porém, não basta incluir o valor dos likes no momento em que criamos Filme, pois este será um elemento incremental. Como faremos para definir algo que será modificado posteriormente, e que não será definido no momento da criação do objeto? Devemos ter um método para inserir a informação e modificar seu estado recém criado.

Também definiremos um método com a utilidade de dar like, sem receber parâmetros e que, no fim, adicionará +1 à contagem de likes.

class Filme:
    def __init__(self, nome, ano, duracao):
        self.nome = nome.title()
        self.ano = ano
        self.duracao = duracao

    def dar_like(self):
        self.likes += 1

Conseguimos dar likes, mas e a exibição desse valor? Para isto, podemos criar uma função, ou colocar likes dentro do construtor. Mas dessa vez sua utilidade não será para definir um valor específico, e sim, inicial. No caso, será igual a 0.

class Filme:
    def __init__(self, nome, ano, duracao):
        self.nome = nome.title()
        self.ano = ano
        self.duracao = duracao
        self.likes = 0

    def dar_like(self):
        self.likes += 1

O próximo passo será replicar o mesmo comportamento para Serie.

class Serie:
    def __init__(self, nome, ano, temporadas):
        self.nome = nome.title()
        self.ano = ano
        self.temporadas = temporadas
        self.likes = 0

    def dar_like(self):
        self.likes += 1

Lembre-se que no construtor não iremos receber likes, ele sempre começará com o valor igual a 0, sem termos influência do usuário. Agora, adicionaremos o texto da string para exibirmos a popularidade.

vingadores = Filme('vingadores - guerra infinita', 2018, 160)
print(f'Nome: {vingadores.nome} - Ano: {vingadores.ano} '
f'- Duração: {vingadores.duracao} - Likes: {vingadores.likes}')

atlanta = Serie('atlanta', 2018, 2)

print(f'Nome: {atlanta.nome} - Ano: {atlanta.ano} '
f'- Temporadas: {atlanta.temporadas} - Likes: {atlanta.likes}')

Temos muitos trechos de código repetido, mas resolveremos isso mais adiante. Em seguida, executaremos o código:

Nome: Vingadores - Guerra Infinita - Ano: 2018 - Duração: 160 - Likes: 0
Nome: Atlanta - ano: 2018 - Temporadas: 2 - Likes: 0

Para adicionarmos um like, podemos usar a função dar_like(), o que faremos duas vezes para atlanta e uma para vingadores.

vingadores = Filme('vingadores - guerra infinita', 2018, 160)
print(f'Nome: {vingadores.nome} - Ano: {vingadores.ano} '
f'- Duração: {vingadores.duracao} - Likes: {vingadores.likes}')
vingadores.dar_like()

atlanta = Serie('atlanta', 2018, 2)

print(f'Nome: {atlanta.nome} - Ano: {atlanta.ano} '
f'- Temporadas: {atlanta.temporadas} - Likes: {atlanta.likes}')

atlanta.dar_like()
atlanta.dar_like()

Entretanto, se executarmos o código, o valor de Likes continuará igual a 0. Por que isso aconteceu? A questão é que incluímos o like após o print(), e resolveremos o assunto se mudarmos a ordem das linhas.

vingadores = Filme('vingadores - guerra infinita', 2018, 160)
vingadores.dar_like()
print(f'Nome: {vingadores.nome} - Ano: {vingadores.ano} '
f'- Duração: {vingadores.duracao} - Likes: {vingadores.likes}')


atlanta = Serie('atlanta', 2018, 2)
atlanta.dar_like()
atlanta.dar_like()
print(f'Nome: {atlanta.nome} - Ano: {atlanta.ano} '
f'- Temporadas: {atlanta.temporadas} - Likes: {atlanta.likes}')

Com os print()s depois dos likes, teremos o seguinte resultado:

Nome: Vingadores - Guerra Infinita - Ano: 2018 - Duração: 160 - Likes: 1
Nome: Atlanta - ano: 2018 - Temporadas: 2 - Likes: 2

Já conseguimos dar likes, fizemos as tarefas propostas, mas temos algumas falhas. Por exemplo, definimos que o nome é titularizado, porém, se adicionarmos uma nova linha com atlanta.nome no código, logo abaixo de atlanta, ele deixará de fazer a alteração nas letras.

atlanta = Serie('atlanta', 2018, 2)

atlanta.nome = 'atlanta'
atlanta.dar_like()
atlanta.dar_like()
print(f'Nome: {atlanta.nome} - Ano: {atlanta.ano} '
f'- Temporadas: {atlanta.temporadas} - Likes: {atlanta.likes}')

No console, veremos:

Nome: Vingadores - Guerra Infinita - Ano: 2018 - Duração: 160 - Likes: 1
Nome: atlanta - ano: 2018 - Temporadas: 2 - Likes: 2

O problema aconteceu porque não estamos protegendo o nome do atributo, este é alterado apenas no momento da criação, mas e depois? Como definiremos set do atributo, ou seja, seu valor? Veremos como proteger a criação do atributo mais adiante.

Sobre o curso Python 3: Avançando na orientação a objetos

O curso Python 3: Avançando na orientação a objetos possui 159 minutos de vídeos, em um total de 62 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!

  • 1150 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

Premium

  • 1150 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$75
à vista R$900
Matricule-se

Premium Plus

  • 1150 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$100
à vista R$1.200
Matricule-se

Max

  • 1150 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$120
à vista R$1.440
Matricule-se
Procurando planos para empresas?
Acesso por 1 ano
Estude 24h/dia onde e quando quiser
Novos cursos toda semana