O que de fato é Python? De acordo com o Guido van Rossum, Python é:
- “High-level programming language, and its core design philosophy is all about code readability and a syntax which allows programmers to express concepts in a few lines of code.”
Ou seja, é uma linguagem de programação com a filosofia de que a legibilidade do código e a sintaxe permitem que o desenvolvedor consiga se expressar em poucas linhas de código.
Para mim, o primeiro grande motivo de ter aprendido Python foi o fato de ser uma linguagem bonita e elegante. Eu me sinto bem expressando meus pensamentos e lógicas em Python – é natural.
Outro grande motivo é que podemos usar Python em diferentes áreas: ciência de dados, desenvolvimento web e aprendizado de máquina (são exemplos que brilham aqui). Google, Netflix, Quora, Pinterest e Spotify estão usando Python, por exemplo. E, entre as empresas brazucas, temos a Geekie, Globo.com, Nuveo, Loggi, entre muitas outras. Vamos aprender um pouco sobre isso.
O básico
1. Variáveis
Podemos pensar em variáveis como palavras que guardam um valor. Simples assim.
Em Python, é bastante fácil definir uma variável e atribuir um valor à ela. Vamos imaginar que queremos armazenar um valor 1 em uma variável chamada
one
:one = 1
Prontinho! Simples, não? Atribuímos o valor 1 à variável
one
. Conseguimos ter inúmeras variáveis.two = 2
some_number = 10000
Como vimos no código acima, temos a variável
two
e atribuímos o valor 2
(um número inteiro). E nossa outra variável some_number
com o valor 10000
armazenado.
Além disso, conseguimos atribuir vários tipos de valores em nossas variáveis, além de números inteiros. Conseguimos lidar com valores booleanos (
True
/False
), strings, números reais e outros tipos de dados.# booleans
true_boolean = True
false_boolean = False
# string
my_name = "Leandro Tk"
# float
book_price = 15.80
Os valores booleanos são
True
e False
. Temos a variável true_boolean
e false_boolean
, que vão representar esses valores. A variável my_name
guarda o valor do tipo string
, que no caso, o valor é Leandro Tk
. E, por último, um número com ponto flutuante armazenado na variável book_price.
Mas, por hora, vamos apenas entender que existem vários tipos de dados e mais para frente vamos falar como usaremos esses dados de diferentes maneiras.
2. Controle de fluxo: condicionais
A expressão
if
avalia se a declaração é True
ou False
. Se a declaração for True
, o código dentro do if
é executado. Vamos ver um exemplo:if True:
print("Hello Python If")
if 2 > 1:
print("2 is greater than 1")
No primeiro código temos a declaração com o valor True. Ou seja, nosso
print("Hello
Python If")
é executado.
Já no segundo, temos a declaração com a “pergunta”
2 é maior que 1?
. A resposta óbvia é que sim, ou seja, é avaliada para True
. Logo, nosso código dentro do if
é executado.
Temos o
else
também. E esse código somente é executado caso a expressão seja False
.if 1 > 2:
print("1 is greater than 2")
else:
print("1 is not greater than 2")
Neste caso,
1 é menor que 2
, então o código dentro do if
não é executado e o código do else, sim.
Temos também o
elif
, que basicamente significa else if
, ou seja, espera uma expressão, como nesse próximo exemplo:if 1 > 2:
print("1 is greater than 2")
elif 2 > 1:
print("1 is not greater than 2")
else:
print("1 is equal to 2")
- if: pergunta se
1 é maior que 2
:False
, então não executa o código e passa para oelif
- elif: pergunta se
2 é maior que 1
:True
. Logo, o códigoprint("1
is not greater than 2")
é executado
Caso o
elif
tivesse um valor False
, o código executado seria o else
.3. Looping/Iterador
Em Python, temos várias formas de iterar, ou seja, fazer uma repetição do código. Vamos conversar aqui sobre dois deles: while e for.
Iterando com while: enquanto a declaração tiver o valor True, o código dentro do bloco continuará sendo executado.
No exemplo a seguir nosso código fará o
print
dos números de 1 a 10:num = 1
while num <= 10:
print(num)
num += 1
O
while
precisa de um loop condition
, ou seja, uma condição, uma declaração que significa continuar
ou parar
a iteração. Se o loop
condition
for True
, continua o loop. Se for False
, o loop para de executar o código dentro do bloco do while.
Neste exemplo, o
num
é inicializado com 1
e o primeiro loop condition
é 1 <= 10
e o resultado é True
. Ou seja, continuamos a executar o bloco. Para cada iteração o num
é incrementado.
Quando o
num
chega a 11
, o loop condition
se torna False
e é hora de deixar o bloco de código. Outro código para entendermos melhor o while:loop_condition = True
while loop_condition:
print("Loop Condition keeps: %s" %(loop_condition))
loop_condition = False
O
loop_condition
é inicializado com True
, logo, continua a iterar, até que atualizemos a variável loop_condition
para ser False
e saiamos do loop.
Iterando com for: definimos uma variável que representará o valor de cada iteração. Vamos ver esse exemplo:
for i in range(1, 11):
print(i)
Neste caso, definimos a variável
i
, que vai representar cada valor da iteração, começando por 1
e terminando em 10
.
Dentro do bloco do for, executamos o print de cada valor
i
.Listas (ou coleções, ou vetores, ou arrays)
Imagine que vamos armazenar o número inteiro
1
em alguma variável, mas talvez queiramos armazenar o inteiro 2
também. E o 3
, 4
, 5
, etc.
Será que temos alguma outra maneira de armazenar valores inteiros sem precisar de
1
milhão de variáveis
? Sim! Vamos falar sobre listas.Listas
são estruturas de dados
, ou seja, podemos armazenar uma lista de valores dentro delas. Vamos usá-las!my_integers = [1, 2, 3, 4, 5]
Bem simples, não? Aqui criamos uma lista com nome
my_integers
com os valores inteiros de 1 a 5.
Mas você pode estar se perguntando:
- “Como podemos pegar um valor dessa lista?”
Boa pergunta! A
lista
tem o conceito de índice
(ou index). O primeiro valor da lista tem o índice 0. O segundo tem o 1, e assim por diante.
Para ficar claro, vamos representar essa lista e cada elemento com seu respectivo índice:
Aqui temos uma lista com os valores 5, 7, 1, 3 e 4. O valor 5 tem o índice 0 e assim por diante.
Usaremos Python para entender melhor essa ideia na prática:
my_integers = [5, 7, 1, 3, 4]
print(my_integers[0]) # 5
print(my_integers[1]) # 7
print(my_integers[4]) # 4
Armazenamos os valores na lista
my_integers
e usamos o código my_integer[0]
para acessar o valor que está no índice 0. Ou seja, o valor 5. Testamos para o índice 1 e 4 também.
Agora imagine que não queremos apenas armazenar números inteiros. Vamos guardar uma lista com os nomes das pessoas da minha família:
relatives_names = [
"Toshiaki",
"Juliana",
"Yuji",
"Bruno",
"Kaio"
]
print(relatives_names[4]) # Kaio
Criamos a lista
relatives_names
e guardamos todos os nomes, depois acessamos o nome que está no índice 4. Nesse caso, o Kaio
. Legal, funcional igualmente aos números inteiros.
Bom, acabamos de aprender como os índices de uma lista funcionam , mas ainda preciso mostrar como adicionar mais valores para uma lista.
O método mais comum para adicionar um novo elemento na lista se chama
append
. Vamos ver como funciona:bookshelf = []
bookshelf.append("The Effective Engineer")
bookshelf.append("The 4 Hour Work Week")
print(bookshelf[0]) # The Effective Engineer
print(bookshelf[1]) # The 4 Hour Work Week
O
append
é super simples. Só precisamos passar o novo valor como parâmetro do método.
Neste exemplo, definimos a lista
bookshelf
– uma lista vazia, nenhum valor pré-adicionado. Depois usamos o método append
duas vezes: um para adicionar o livro The Effective Engineer e depois para adicionar outro livro The 4 Hour Work Week
. Se acessarmos o valor no índice 0, vamos obter o livro The Effective Engineer
, por exemplo.
Bom, por hora é o suficiente sobre listas. Agora vamos falar sobre outra estrutura de dados.
Dicionário: estrutura de dados de chave-valor
Agora sabemos que as listas usam números inteiros como índices, mas e se não quisermos usar números inteiros nos nossos índices? Alguma estrutura de dados que possamos usar índices como número, string ou outro tipo de valor.
Vamos aprender sobre Dicionários. Um dicionário é uma estrutura de dados, uma coleção de pares
chave-valor
.
Vamos ver como funciona na prática:
dictionary_example = {
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
A
chave
é o “índice” que aponta para um valor
. Neste exemplo, a chave "key1"
aponta para o valor "value1"
.
Como acessamos o valor no dicionário? Usando a
chave
.dictionary_tk = {
"name": "Leandro",
"nickname": "Tk",
"nationality": "Brazilian"
}
print("My name is %s" %(dictionary_tk["name"])) # My name is Leandro
print("But you can call me %s" %(dictionary_tk["nickname"])) # But you can call me Tk
print("And by the way I'm %s" %(dictionary_tk["nationality"])) # And by the way I'm Brazilian
Aqui criamos um dicionário
dictionary_tk
com informações sobre mim: meu nome, apelido e nacionalidade. Cada atributo é uma chave
no dicionário.
Assim como aprendemos como acessar um valor da lista usando índices, também podemos usar índice (no caso dos dicionários —
chaves
) para acessar um valor do dicionário.
Neste exemplo, acessamos todos os atributos do dicionário.
- Pegar o nome:
dictionary_tk["name"]
- Pegar o apelido:
dictionary_tk["nickname"]
- Pegar a nacionalidade:
dictionary_tk["nationality"]
Bem simples, não?
Outro conceito legal de dicionários é que podemos usar qualquer outro tipo de dados como valor. Nesse próximo exemplo vamos usar um inteiro como valor:
dictionary_tk = {
"name": "Leandro",
"nickname": "Tk",
"nationality": "Brazilian",
"age": 24
}
print("My name is %s" %(dictionary_tk["name"])) # My name is Leandro
print("But you can call me %s" %(dictionary_tk["nickname"])) # But you can call me Tk
print("And by the way I'm %i and %s" %(dictionary_tk["age"], dictionary_tk["nationality"])) # And by the way I'm Brazilian
Complementando aquele primeiro exemplo, agora adicionamos a
chave
“age” e colocamos 24 como valor
.
E assim como adicionamos novos valores na lista, podemos fazer isso também em dicionários. Lembra que uma
chave
sempre aponta para um valor
? Esse conceito é uma parte essencial do dicionário, e isso também é verdade quando falamos sobre adicionar novos valores para essa estrutura de dados.dictionary_tk = {
"name": "Leandro",
"nickname": "Tk",
"nationality": "Brazilian"
}
dictionary_tk['age'] = 24
print(dictionary_tk) # {'nationality': 'Brazilian', 'age': 24, 'nickname': 'Tk', 'name': 'Leandro'}
Neste exemplo temos o dicionário
dictionary_tk
com os valores name
, nickname
e nationality
, mas agora queremos adicionar um novo par age
com o valor 24
. Simplesmente atribuímos o valor 24 para a chave age no dicionário dictionary_tk
. Nada muito complicado aqui.Repetição: iterando estruturas de dados
Assim como aprendemos no Python básico, a iteração em listas é bem simples. Nós, desenvolvedores Python, usamos comumente o
for
loop:bookshelf = [
"The Effective Engineer",
"The 4 hours work week",
"Zero to One",
"Lean Startup",
"Hooked"
]
for book in bookshelf:
print(book)
A primeira coisa é definir a nossa lista. No caso,
bookshelf
, que contém livros como strings, então iteramos com o for. Para cada livro (book
) no bookshelf
, vamos imprimir esse valor.book
é uma variável que definimos dentro do escopo do for
. Ou seja, é apenas um nome que definimos. Podemos trocar esse nome por qualquer outra coisa, por exemplo: bla
. Usamos book
nesse caso por semântica.
Agora, para iterar um dicionário, também podemos usar o
for
loop, mas temos acesso à chave, ao invés do valor:dictionary = { "some_key": "some_value" }
for key in dictionary:
print("%s --> %s" %(key, dictionary[key]))
# some_key --> some_value
Neste exemplo definimos a variável
key
, que representa cada chave do dicionário. Para cada iteração, vamos imprimir a chave e o valor correspondente àquela chave.
Outra forma de iterar um dicionário é utilizar o método
items()
para que tenhamos acesso não apenas à chave, mas também ao valor:dictionary = { "some_key": "some_value" }
for key, value in dictionary.items():
print("%s --> %s" %(key, value))
# some_key --> some_value
Neste exemplo vemos que agora definimos duas variáveis para cada iteração:
key
e value
. Agora temos acesso à ambos os atributos do dicionário.
Vamos a outro exemplo:
dictionary_tk = {
"name": "Leandro",
"nickname": "Tk",
"nationality": "Brazilian",
"age": 24
}
for attribute, value in dictionary_tk.items():
print("My %s is %s" %(attribute, value))
# My name is Leandro
# My nickname is Tk
# My nationality is Brazilian
# My age is 24
Aqui voltamos àquele dicionário
dictionary_tk
com as minhas informações. Usamos o método items()
para acessar a chave e valor que definimos como attribute
e value
, respectivamente. Para cada iteração estamos imprimindo novamente.Classes & Objetos
Um pouco de teoria:
Objetos são uma tentativa de representação de objetos do mundo real como, por exemplo, carros, cachorros ou bicicletas. Os objetos compartilham duas principais características:
dados
e comportamentos
.
Vamos pegar o carro como exemplo. Carros têm
dados
como número de rodas, número de portas e capacidade de assentos, e também possui comportamentos
: aceleram, freiam, mostram a quantidade de combustível e muitas outras coisas.
Nós identificamos dados como atributos e
comportamentos
como métodos
em programação orientada a objetos.- Dados → Atributos
- Comportamentos → Métodos
Outro conceito importante são as classes. A
Classe
é um modelo, uma abstração, um molde que os objetos se baseiam para serem criados.
No mundo real, comumente achamos muitos objetos que se agrupam no mesmo “tipo”, como carros. Todos com o mesmo modelo (todos têm um motor, rodas, portas, e assim por diante). Cada carro é criado por esse mesmo modelo, com os mesmos componentes.
Programação Orientada a Objetos em Python
Python, como uma linguagem orientada a objetos, tem esses conceitos:
classe
e objeto
.
Relembrando: a classe é um modelo para um objeto, uma maneira para definir
atributos
e métodos
.
Agora queremos definir uma classe veículo (
Vehicle
) em Python. Veremos como a sintaxe de uma classe é definida em Python:class Vehicle:
pass
Definimos uma classe com o termo
class
– e apenas isso. Simples, não? E agora vamos criar objetos a partir desse modelo, dessa classe que definimos.car = Vehicle()
print(car) # <__main__.Vehicle instance at 0x7fb1de6c2638>
Aqui temos o
car
, um objeto
da classe Vehicle
(um objeto também é comumente chamado de instância de uma classe).
Lembrando que a nossa classe
Vehicle
tem quatro atributos
: número de rodas, tipo de tanque, capacidade de assentos e velocidade máxima. Atribuímos esses valores quando criamos o objeto. Esse é um exemplo de como passamos os dados dos atributos quando inicializamos o objeto:class Vehicle:
def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity):
self.number_of_wheels = number_of_wheels
self.type_of_tank = type_of_tank
self.seating_capacity = seating_capacity
self.maximum_velocity = maximum_velocity
Usamos o método
init
. Chamamos ele de método construtor – ele constrói um objeto a partir da classe definida. Então, quando criamos um novo objeto, precisamos passar para esse método os dados dos atributos.
Imagine que amamos o Tesla Model S e queremos criar um objeto desse modelo. Tem quatro rodas, movido à energia elétrica, possui cinco assentos e a sua velocidade máxima é de 250km/h. Hora de criar!
tesla_model_s = Vehicle(4, 'electric', 5, 250)
number_of_wheel
: 4type_of_tank
: ‘electric’seating_capacity
: 5maximum_velocity
: 250
Todos os valores atribuídos. Mas como acessamos esses valores? Usamos os métodos, que são os comportamentos dos objetos. Vamos implementar isso:
class Vehicle:
def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity):
self.number_of_wheels = number_of_wheels
self.type_of_tank = type_of_tank
self.seating_capacity = seating_capacity
self.maximum_velocity = maximum_velocity
def number_of_wheels(self):
return self.number_of_wheels
def set_number_of_wheels(self, number):
self.number_of_wheels = number
Aqui temos a implementação de dois métodos:
number_of_wheels
e set_number_of_wheels
. Chamamos de getter
& setter
.- getter: retorna o valor do atributo
- setter: atribui um novo valor ao atributo
Em Python, podemos usar o
@property
(decorator
) para definir getters
e setters
:class Vehicle:
def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity):
self.number_of_wheels = number_of_wheels
self.type_of_tank = type_of_tank
self.seating_capacity = seating_capacity
self.maximum_velocity = maximum_velocity
@property
def number_of_wheels(self):
return self.__number_of_wheels
@number_of_wheels.setter
def number_of_wheels(self, number):
self.__number_of_wheels = number
Dessa forma podemos usar esses métodos para acessar ou setar atributos:
tesla_model_s = Vehicle(4, 'electric', 5, 250)
print(tesla_model_s.number_of_wheels) # 4
tesla_model_s.number_of_wheels = 2 # setting number of wheels to 2
print(tesla_model_s.number_of_wheels) # 2
Agora vamos implementar um método que produz o som do carro. Vamos chamar esse método de
make_noise
:class Vehicle:
def __init__(self, number_of_wheels, type_of_tank, seating_capacity, maximum_velocity):
self.number_of_wheels = number_of_wheels
self.type_of_tank = type_of_tank
self.seating_capacity = seating_capacity
self.maximum_velocity = maximum_velocity
def make_noise(self):
print('VRUUUUUUUM')
Agora chamaremos esse método com nosso objeto e ele vai imprimir a string “VRRRRUUUUM.”
tesla_model_s = Vehicle(4, 'electric', 5, 250)
tesla_model_s.make_noise() # VRUUUUUUUM
Encapsulamento: ocultando informações
Encapsulamento é uma técnica para restringir acesso direto aos dados e métodos de um objeto. Mas, ao mesmo tempo, ele facilita operações em cima desses dados através de métodos (públicos — já já vamos falar sobre isso).
- “Encapsulation can be used to hide data members and members function. Under this definition, encapsulation means that the internal representation of an object is generally hidden from view outside of the object’s definition.” — Wikipedia
Toda representação de um objeto fica ocultado do mundo externo. Apenas o próprio objeto consegue interagir com seus dados internos.
Então, primeiro precisamos entender como atributos e métodos
públicos
e não-públicos
funcionam.Atributos públicos
Para uma classe Python, podemos inicializar um
atributo público
dentro do nosso método construtor:class Person:
def __init__(self, first_name):
self.first_name = first_name
Neste exemplo passamos o valor de
first_name
como parâmetro e atribuímos ao nosso atributo público
(no caso, self.first_name
).tk = Person('TK')
print(tk.first_name) # => TK
Dentro da classe:
class Person:
first_name = 'TK'
Neste exemplo não passamos o valor no método construtor. Apenas definimos esse atributo dentro da classe e, nesse caso, todos os objetos instanciados da classe (criados a partir da classe) terão esse atributo de classe inicializado com o valor “
TK
“.tk = Person()
print(tk.first_name) # => TK
Legal! Agora aprendemos como podemos usar
atributos públicos
tanto a nível de instâncias, quanto de classes. Outra coisa interessante sobre a parte pública
é que podemos gerenciar o valor desse atributo.
O que eu quero dizer com isso? Nosso objeto pode gerenciar os valores de seus atributos: usando
Get
e Set
para esses atributos.
Continuando com a ideia da classe
Person
, agora queremos atribuir um novo valor para o atributo first_name
:tk = Person('TK')
tk.first_name = 'Kaio'
print(tk.first_name) # => Kaio
Pronto, atualizamos o nosso atributo
first_name
para um novo valor (Kaio
). Bem simples. Dado que é um atributo público, podemos atribuir novos valores sem tantos problemas.Atributos não-públicos
- We don’t use the term “private” here, since no attribute is really private in Python (without a generally unnecessary amount of work). — PEP 8
Observação: A PEP 8 é um Style Guide for Python Code, ou seja, um guia de boas práticas para escrever código Python. E como boa prática, desenvolvedores Python não usam o termo “privado” para atributos, dado que um atributo em Python não é realmente privado. Por isso, usamos o termo “
não-público
“.
Assim como nosso
atributo
público
, também podemos definir o nosso atributo não-público
no método construtor e dentro da classe. A única diferença de sintaxe é que para atributos não-públicos
, usamos o underscore (_
) antes do nome do atributo.- “‘Private’ instance variables that cannot be accessed except from inside an object don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member)” — Python Software Foundation
Como escrito na Python Software Foundation, não existem atributos privados, e sim atributos não-públicos com a convenção de usar underscore.
Aqui um exemplo:
class Person:
def __init__(self, first_name, email):
self.first_name = first_name
self._email = email
Veja o atributo
self._email
. É dessa forma que definimos um atributo não-público.tk = Person('TK', 'tk@mail.com')
print(tk._email) # tk@mail.com
- We can access and update it.
Non-public variables
are just a convention and should be treated as a non-public part of the API.
E, no texto da Python Software Foundation, é enfatizado que podemos acessar e atualizar esses valores não-públicos, dado que é apenas uma convenção. Mas como convenção, deve ser respeitada como uma parte não-pública de uma classe.
Para seguir essa convenção de não acessar diretamente nossos atributos não-públicos, usamos métodos para isso. Vamos implementar dois métodos (
email
e update_email
) para entender como isso funciona:class Person:
def __init__(self, first_name, email):
self.first_name = first_name
self._email = email
def update_email(self, new_email):
self._email = new_email
def email(self):
return self._email
Agora podemos acessar esses atributos não-públicos usando métodos (públicos):
tk = Person('TK', 'tk@mail.com')
print(tk.email()) # => tk@mail.com
# tk._email = 'new_tk@mail.com' -- treat as a non-public part of the class API
print(tk.email()) # => tk@mail.com
tk.update_email('new_tk@mail.com')
print(tk.email()) # => new_tk@mail.com
- 1 – Inicializamos um novo objeto com o
first_name
TK ee-mail
tk@mail.com - 2 – Imprimimos o e-mail acessando o atributo não-público com o método
- 3 – Tentamos atribuir um novo valor para o atributo
e-mail
de fora da nossa classe - 4 – Precisamos tratar e respeitar nossa convenção de
atributos não-públicos
como uma parte não pública da classe - 5 – Atualizamos nosso atributo com nosso método (público)
- 6 – Sucesso! Conseguimos atualizar o dado do nosso atributo com ajuda do nosso método
Métodos públicos
Assim como atributos públicos, os métodos públicos também têm acesso direto de fora da classe:
class Person:
def __init__(self, first_name, age):
self.first_name = first_name
self._age = age
def show_age(self):
return self._age
Vamos testar:
tk = Person('TK', 25)
print(tk.show_age()) # => 25
Funciona como esperado. Podemos acessar sem problemas.
Métodos não-públicos
Mas com métodos não-públicos, não podemos acessá-los, por convenção. Vamos implementar a mesma classe
Person
, mas agora com um método não-público show_age
usando underscore:class Person:
def __init__(self, first_name, age):
self.first_name = first_name
self._age = age
def _show_age(self):
return self._age
Agora tentaremos chamar esse método com nosso objeto:
tk = Person('TK', 25)
print(tk._show_age()) # => 25
- We can access and update it. Non-public methods are just a convention and should be treated as a non-public part of the API
Assim como nossos atributos, nosso método não-público é apenas uma convenção.
Esse próximo exemplo mostra como podemos usar esses métodos:
class Person:
def __init__(self, first_name, age):
self.first_name = first_name
self._age = age
def show_age(self):
return self._get_age()
def _get_age(self):
return self._age
tk = Person('TK', 25)
print(tk.show_age()) # => 25
Neste exemplo implementamos o método
_get_age
que tratamos como não-público. Ou seja, só podemos usá-lo a nível de classe (dentro da nossa classe). Depois implementamos o método (nesse caso, público) show_age
, que usa o método _get_age
para poder acessar o atributo age
.
Agora, fora da nossa classe, podemos usar o
show_age
, nosso método público, e apenas acessar o_get_age
de dentro da nossa classe. Lembrando de novo: é uma questão de convenção.Resumo do Encapsulamento
Com encapsulamento podemos garantir que a representação interna (atributos e métodos) do nosso objeto está oculta e fora da nossa classe.
Herança: herdando comportamentos e características
Alguns objetos têm algumas coisas em comum: seus comportamentos e características. Por exemplo, eu herdei algumas características e comportamentos dos meus pais.
Como característica, herdei os olhos e cabelo. Como comportamento, a introversão. Em programação orientada a objetos, classes podem herdar características (dados) e comportamentos (métodos) comuns de outra classe. Agora vamos ver um exemplo e implementá-lo em Python.
Imagine um carro. Número de rodas, capacidade de assentos e velocidade máxima são todos atributos de um carro. Podemos falar que um carro elétrico possui esses mesmos atributos, ou seja, ele pode herdar essas características do carro.
Implementando a classe
Car
:class Car:
def __init__(self, number_of_wheels, seating_capacity, maximum_velocity):
self.number_of_wheels = number_of_wheels
self.seating_capacity = seating_capacity
self.maximum_velocity = maximum_velocity
Instanciamos o objeto e podemos acessar normalmente nossos atributos:
my_car = Car(4, 5, 250)
print(my_car.number_of_wheels)
print(my_car.seating_capacity)
print(my_car.maximum_velocity)
Agora queremos implementar a classe
ElectricCar
que vai herdar da classe Car
. Em Python, passamos a classe “pai” (no caso, a classe Car
) como parâmetro da classe “filha” (ElectricCar
).class ElectricCar(Car):
def __init__(self, number_of_wheels, seating_capacity, maximum_velocity):
Car.__init__(self, number_of_wheels, seating_capacity, maximum_velocity)
Simples assim. Passamos o Car como parâmetro de
ElectricCar
e usamos o método construtor para inicializar os nossos atributos. Não precisamos de mais nenhum método ou definição de atributos, dado que a nossa classe ElectricCar
já herda todas essas características. Vamos testar!my_electric_car = ElectricCar(4, 5, 250)
print(my_electric_car.number_of_wheels) # => 4
print(my_electric_car.seating_capacity) # => 5
print(my_electric_car.maximum_velocity) # => 250
Funciona perfeitamente! Podemos acessar nossos atributos sem problemas, apenas herdando da classe
Car
.
E é isso!
Aprendemos muitas coisas sobre o básico de Python:
- Como as variáveis em Python funcionam
- Como funciona o controle de fluxo — condicionais
- Como Python lida com loop, iteração, mais especificamente
while
efor
- Como listas funcionam
- Dicionários, uma estrutura de dados de chave-valor
- Como iteramos sobre essas estruturas de dados
- Objetos e Classes
- Atributos como dados de um objeto
- Métodos como comportamento de um objeto
- Usando getters e setters em Python & decorator property
- Encapsulamento: ocultando informações
- Herança: herdando comportamentos e características
Parabéns! Você completou um conteúdo denso sobre Python!
Para mais artigos sobre desenvolvimento de software, Python e programação em geral, me acompanhe no portal.
Have fun, keep learning, and always keep coding
Nenhum comentário:
Postar um comentário