diff --git a/content/aulas/intro-py/index.md b/content/aulas/intro-py/index.md index 1aa8814..09af176 100644 --- a/content/aulas/intro-py/index.md +++ b/content/aulas/intro-py/index.md @@ -25,13 +25,13 @@ vlr_dolar = 4.95 O valor `4.95` está agora salvo na memória do meu computador. Para obter o valor, eu chamo `vlr_dolar`. Assim: ```py -print(vlr_dolar) # A função `print()` é usada para imprimir em tela +print(vlr_dolar) ``` ```textfile 4.95 ``` -Uma variável serve, entre outros, para que não precisemos repetir a digitação ou operação sempre que precisamos do valor. Vamos pegar como exemplo o último verso de "A flor e a náusea", de Carlos Drummond de Andrade: +Uma variável serve, entre outros, para que não precisemos repetir a digitação ou operação para obter o valor. Vamos pegar como exemplo este verso de "A flor e a náusea", de Carlos Drummond de Andrade: > É feia. Mas é uma flor. Furou o asfalto, o tédio, o nojo e o ódio. @@ -150,7 +150,7 @@ Neste capítulo vimos: - documentação: [https://docs.python.org/pt-br/3/library/functions.html#print](https://docs.python.org/pt-br/3/library/functions.html#print) {{< /expandable >}} {{< expandable label="Tipos de dados" level="2" >}} -Repare que, quando usamos variáveis, às vezes usamos valores com aspas, e outras vezes sem aspas. Exemplos: +Repare que, quando trabalhamos com variáveis, às vezes usamos valores com aspas, e outras vezes sem aspas. Exemplos: ```py pi = 3.1416 @@ -169,7 +169,7 @@ Isso porque os valores são de tipos diferentes: o primeiro pertence ao tipo num ```py numero = 32 print(numero) -print(type(numero)) # a função type() mostra o tipo de dado +print(type(numero)) ``` ```textfile 32 @@ -253,7 +253,7 @@ Brasil registra 94 mortes por dengue; Belo Horizonte decreta emergência txt = 65.1 print(txt) print(type(txt)) -txt = float(txt) # conversão para `str` +txt = str(txt) # conversão para `str` print(txt) print(type(txt)) ``` @@ -265,7 +265,7 @@ print(type(txt)) ``` {{< warning >}} -Fique atento! Se colocamos `"` ou `'` (aspas usadas em `str`) num valor numérico (digamos, `int`), o número deixa de ser número, e se transforma em texto. Uma mudança que parece pequena muda completamente o tipo do dado. +Fique atento! Se colocamos `"` ou `'` (aspas usadas em `str`) num valor numérico (digamos, `int`), o número deixa de ser número e se transforma em texto. Uma mudança que parece pequena muda completamente o tipo do dado. ```py print(1234) @@ -279,6 +279,16 @@ print(type('1234')) 1234 ``` + +```py +print(12 + 34) +print('12' + '34') +``` +```textfile +46 +1234 +``` + {{< /warning >}} {{< warning >}} @@ -317,7 +327,7 @@ print("O mesmo acontece com "aspas duplas" dentro de aspas duplas?") SyntaxError: invalid syntax. Perhaps you forgot a comma? ``` -Nos dois erros acima, o sistema não entende se as aspas servem para indicar `str` ou se são grifo. temos `SyntaxError`, erro de sintaxe. Isso ocorre porque a máquina entende que os dados se encerram no fechamento de aspas e não sabe o que fazer com o restante da informação: +Nos dois erros acima, o sistema não entende se as aspas servem para indicar `str` ou se são grifo. Temos `SyntaxError`, erro de sintaxe. Isso ocorre porque a máquina entende que os dados se encerram no fechamento de aspas e não sabe o que fazer com o restante da informação: 1. No primeiro erro, a máquina computou `'O que acontece se, dentro de '` e não soube o que fazer com o resto; 2. No segundo exemplo, a máquina computou `"O mesmo acontece com "` e não soube o que fazer com o resto. @@ -425,21 +435,22 @@ print(sal_minimo / dias_uteis) 64.18181818181818 ``` -...ou então, calcular a área de um círculo de 12,5 metros de raio, cuja fórmula é \\(A=\pi r^2\\). +...ou então, calcular a área de um círculo de \\(n\\) metros de raio, cuja fórmula é \\(A=\pi r^2\\). ```py -raio = 12.5 +raio = input("Digite o valor do raio: ") pi = 3.14159 -area = pi * (raio**2) +area = pi * (float(raio)**2) print(area) ``` ```textfile +Digite o valor do raio: 12.5 490.87343749999997 ``` No primeiro exemplo, eu dividi o salário mínimo (`sal_minimo`) pela quantidade de dias úteis (`dias_uteis`) em um mês. Para isso, usei o símbolo de divisão (`/`). -No segundo exemplo, elevei o raio (`raio`) ao quadrado usando o símbolo de exponenciação (`**`) e, a ele, multipliquei o valor de pi (`pi`) com o símbolo de multiplicação (`*`). +No segundo exemplo, elevei ao quadrado o raio (`raio`) convertido para `float` (`float()`) usando o símbolo de exponenciação (`**`) e, a ele, multipliquei o valor de pi (`pi`) com o símbolo de multiplicação (`*`). Abaixo estão os operadores aritméticos em Python (e nos exemplos, considere `x = 5` e `y = 2`): @@ -527,7 +538,7 @@ print(len(cpf) == qtd_elem_cpf) True ``` -Ou ainda, comparar uma projecao rudimentar da balança comercial com uma meta imaginária: +Ou ainda, comparar uma projeção rudimentar da balança comercial com uma meta imaginária: ```py # fonte: @@ -651,10 +662,24 @@ False --- Neste capítulo vimos: +- a função `input()` + - pede ao usuário um valor e salva numa variável + - todo valor inserido, seja numérico ou não, é tratado como `str` + - documentação: [https://docs.python.org/pt-br/3/library/functions.html#input](https://docs.python.org/pt-br/3/library/functions.html#input) + - a função `len(x)` - retorna a quantidade de elementos no objeto `x` - documentação: [https://docs.python.org/pt-br/3/library/functions.html#len](https://docs.python.org/pt-br/3/library/functions.html#len) {{< /expandable >}} +{{< expandable label="Exercícios - parte 1" level="2" >}} +1. No mês passado, um certo influencer tinha 5.641.981 seguidores no Instagram. Como ele divulgava o "jogo do tigrinho" e a PF bateu na porta dele, o influencer teve uma queda significativa de seguidores: 4.567.093 neste mês. Calcule a queda percentual. +2. Uma certa empresa teve lucro de US$ 12.095.187,05 em dezembro de 2023, com o dólar a R$ 4,8526. Em janeiro de 2024, com o dólar a R$ 4,9163, a empresa teve lucro de US$ 11.567.011,87. Qual é a diferença percentual entre os valores em reais? +3. A fórmula para calcular IMC é: + $$ + IMC = \frac{peso em kg}{altura em metro^{2}} + $$ +Crie um código que peça ao usuário seu peso, sua altura, e retorne o IMC. +{{< /expandable >}} {{< expandable label="Controle de fluxo com `if`" level="2" >}} Até o momento, estamos escrevendo códigos que são executados numa estrutura fixa: __de cima para baixo, linha a linha__. Exemplo: @@ -1133,1063 +1158,3 @@ Crie um programa que: - realize a operação de conversão —se é Celsius, traz resultado em Fahrenheit; se Fahrenheit, em Celsius. {{< /expandable >}} -{{< expandable label="Coleções de dados: lista" level="2" >}} -Em aulas anteriores vimos os tipos primitivos de dados, como: - -- integer (`int`): `4`, `-12`, `6745`... - -- float (`float`): `4.67`, `-12.01973`, `6745.0`... - -- boolean (`bool`): `True`, `False` - -- string (`str`): `"Python"`, `"maçã"`, `"jornalismo de dados"`, `"6.0"`... - -Também vimos como armazenar dados na memória com o uso de variáveis. Por exemplo: - -```py -idade = 43 -nome = "Rodolfo" -print(f"{nome} tem {idade} anos.") -``` - -Muitas vezes, porém, precisamos armazenar mais de um valor numa variável. Por exemplo, as contas do mês: - -```py -# Como eu posso colocar todas as contas distintas numa variável única? -aluguel = 1400 -luz = 110 -agua = 90 -internet = 100 -gas = 25 -cartao = 800 -``` - -Para armazenamos múltiplos dados numa variável, há as __coleções de dados__ do Python. Há quatro coleções muito comuns, cada uma com características e funções próprias. - -### Lista - -A primeira coleção é a __lista__ (classe `list`), feita com valores dentro de colchetes (`[` e `]`) ou simplesmente chamando a função `list()`. - -```py -aluguel = 1400 -luz = 110 -agua = 90 -internet = 100 -gas = 25 -cartao = 800 - -contas = [aluguel, luz, agua, internet, gas, cartao] # Aqui eu crio uma lista - -print(contas) -print(type(contas)) -``` -```textfile -[1400, 110, 90, 100, 25, 800] - -``` -```py -linguagens = ["Python", "SQL", "Javascript", "C++"] -print(linguagens) -print(type(linguagens)) -print(len(linguagens)) -``` -```textfile -['Python', 'SQL', 'Javascript', 'C++'] - -4 -``` - -Posso também misturar tipos de dados dentro de uma lista... - -```py -mix = [12, "Cenoura", 3.72, True] -print(mix) -``` -```textfile -[12, 'Cenoura', 3.72, True] -``` - -...fazer lista de listas... - -```py -lista1 = [1, 2, 3] # Uma lista -lista2 = [4, 5, 6] # Outra lista -listona = [lista1, lista2] # Uma lista com as duas listas -print(listona) -``` -```textfile -[[1, 2, 3], [4, 5, 6]] -``` - -...e juntar várias listas numa só. - -```py -listona2 = lista1 + lista2 -print(listona2) -``` -```textfile -[1, 2, 3, 4, 5, 6] -``` - -Para acessar cada elemento da lista, é preciso usar a posição do elemento dentro de colchetes (`[` e `]`). - -{{< warning >}} -Mas lembre-se: __Python começa a contagem no índice 0__ (ou seja, o primeiro elemento é 0, o segundo é 1, o terceiro é 2...). - -```py -linguagens = ["Python", "SQL", "Javascript", "C++", "Java", "HTML"] -# Índice 0 1 2 3 4 5 -print(f"A linguagem na terceira posição é {linguagens[2]}") -print(f"A linguagem na quarta posição é {linguagens[3]}") -print(f"A linguagem na primeira posição é {linguagens[0]}") -``` -```textfile -A linguagem na terceira posição é Javascript -A linguagem na quarta posição é C++ -A linguagem na primeira posição é Python -``` -{{< /warning >}} - -A indexação permite, inclusive, realizar cálculos: - -```py -lista = [3.14, 2.09, 8.21, -7,55] -print(lista[1] * lista[3]) # Ou seja, 2.09 * -7.55 -``` -```textfile --14.629999999999999 -``` - -É possível, ainda, acessar múltiplos elementos passando o índice de começo e de fim (mas preste atenção: __o resultado exclui o último item__). Funciona assim: `[onde começa:onde termina + 1]` - -```py -linguagens = ["Python", "SQL", "Javascript", "C++", "Java", "HTML"] -# índice 0 1 2 3 4 5 - -print(linguagens[2:5]) # Começa no índice 2 e termina no índice 4 -``` -```textfile -['Javascript', 'C++', 'Java'] -``` - -"E como funciona essa indexação quanto temos uma lista de listas?" Vamos ver com um exemplo: - -```py -exemplo = [["vermelho", "amarelo", "azul"], ["verde", "roxo", "preto"]] -``` - -Neste caso, temos duas listas dentro de uma lista. O desenho é assim: - - - -A variável exemplo tem dois elementos. Cada elemento é uma lista. Então, se eu chamar isso... - -```py -exemplo[1] # o segundo item da variável `exemplo` -``` - -...terei como retorno isso: - -``` -["verde", "roxo", "preto"] # uma lista -``` - -Se eu quero acessar o elemento `"preto"`, preciso então indicar o índice dentro da lista que acesso com `exemplo[1]`. Fica assim: - -```py -exemplo[1][2] # do segundo item, quero o terceiro item, ou seja, "preto" -``` - -Vamos ver na prática: - -```py -exemplo = [["vermelho", "amarelo", "azul"], ["verde", "roxo", "preto"]] -print(exemplo[1]) -print(exemplo[1][2]) -``` -```textfile -['verde', 'roxo', 'preto'] -preto -``` - -Como na aula passada vimos `if`-`elif`-`else`, vale a gente ver o uso de controle de fluxo com listas e apresentar dois operadores —e, para o exemplo abaixo, consideramos `nomes = ["João", "André", "Ana", "Maria"]`: - -| operador | significado | entrada | saída | -| :-: | :-: | :-: | :-: | -| `in` | está contido em | `"João" in nomes` | `True` | -| `not in` | não está contido em | `"Pedro" not in nomes` | `True` | - -```py -nomes = ["João", "André", "Ana", "Maria"] - -print('Ana' not in nomes) -print('Maria' in nomes) -``` -```textfile -False -True -``` - -```py -nome = "Claudio" -lista_nomes = ["Renato", "Ana", "Fernanda"] - -if nome not in lista_nomes: # "Se o nome não estiver na lista..." - print(f"O nome {nome} não está na lista.") -else: - print(f"O nome {nome} está na lista.") -``` -```textfile -O nome Claudio não está na lista. -``` - -As listas são __mutáveis__: posso adicionar e excluir elementos, mostrar em ordem reversa etc. com algumas funções: - -- `.append(x)` para adicionar um elemento `x` -- `.pop(i)` para tirar da lista um elemento de índice i e mostrar esse elemento -- `.remove(x)` para excluir um elemento `x` -- `.reverse()` para inverter a ordem dos elementos -- `.sort()` para organizar os elementos do menor ao maior (ou do maior ao menor, se usar `reverse=True`) -- `.count(x)` para contar quantas vezes o elemento `x` aparece na lista - -```py -lista = ["Carlos", "Antonio", "Cesar"] -print(lista) - -lista.append("Rodolfo") # adicionar "Rodolfo" -print(lista) - -lista.remove("Cesar") # remover "Cesar" -print(lista) - -lista.reverse() # colocar em ordem reversa -print(lista) - -lista.sort(reverse=True) # ordenar do maior para o menor -print(lista) - -print(lista.count("Rodolfo")) # contar quantas vezes aparece "Rodolfo" -``` -```textfile -['Carlos', 'Antonio', 'Cesar'] -['Carlos', 'Antonio', 'Cesar', 'Rodolfo'] -['Carlos', 'Antonio', 'Rodolfo'] -['Rodolfo', 'Antonio', 'Carlos'] -['Rodolfo', 'Carlos', 'Antonio'] -1 -``` -{{< /expandable >}} -{{< expandable label="Coleções de dados: tupla" level="2" >}} -Outra coleção de dados é a tupla (classe `tuple`), feita com valores dentro de parênteses (`(` e `)`) ou com a função `tuple()`. - -```py -valores = (1, 2, 99) -print(valores) -print(type(valores)) -``` -```textfile -(1, 2, 99) - -``` - -Assim como listas, tuplas podem conter dados de tipos variados, e é possível criar uma tupla de tuplas (ou de listas). Também a forma de localizar elementos por meio da indexação é similar. - -```py -tupla_1 = (4, False, "maçã", 8.91) # tupla com diversos tipos -print(tupla_1) - -tupla_2 = ((1, 2, 3), (9, 8, 7)) # tupla contendo duas tuplas -print(tupla_2) - -tupla_3 = tuple([1, 2, 3]) # tupla a partir de lista -print(tupla_3) - -tupla_4 = (("Ana", "Pedro", "Claudio"), ("José", "Maria", "João")) -print(tupla_4[0][2]) # indexação para encontrar "Claudio" -``` -```textfile -(4, False, 'maçã', 8.91) -((1, 2, 3), (9, 8, 7)) -(1, 2, 3) -Claudio -``` - -Entretanto, as semelhanças acabam aí. Ao contrário de listas, __tuplas são imutáveis__. Ou seja, elementos não podem ser removidos, adicionados, reordenados etc. - -```py -vegetais = ("acelga", "repolho", "alface") -vegetais.remove("acelga") -``` -```textfile ---------------------------------------------------------------------------- -AttributeError Traceback (most recent call last) -Cell In[16], line 1 -----> 1 vegetais.remove("acelga") - -AttributeError: 'tuple' object has no attribute 'remove' -``` -```py -vegetais.append("rúcula") -``` -```textfile ---------------------------------------------------------------------------- -AttributeError Traceback (most recent call last) -Cell In[17], line 1 -----> 1 vegetais.append("rúcula") - -AttributeError: 'tuple' object has no attribute 'append' -``` - -Daí a importância de tuplas: __elas são úteis quando precisamos nos certificar de que os elementos não foram ou não serão alterados__. É comum, inclusive, converter listas em tuplas para que seus dados não sejam modificados. - -```py -cores = ["amarelo", "verde", "azul", "vermelho"] -print(f"Temos {type(cores)}, o que permite que eu altere seus elementos: {cores}") - -cores = tuple(cores) # converto a lista para tupla -print(f"Agora temos {type(cores)}, impossibilitando alterações: {cores}") -``` -```textfile -Temos , o que permite que eu altere seus elementos: ['amarelo', 'verde', 'azul', 'vermelho'] -Agora temos , impossibilitando alterações: ('amarelo', 'verde', 'azul', 'vermelho') -``` -{{< /expandable >}} -{{< expandable label="Coleções de dados: conjunto" level="2" >}} -A terceira coleção é o conjunto (classe `set`), feita com valores dentro de chaves (`{` e `}`) ou com a função `set()`. - -```py -conjunto = {1, 2, 3, 4, 5} -print(conjunto) -print(type(conjunto)) -``` -```textfile -{1, 2, 3, 4, 5} - -``` -As diferenças mais significativas entre conjuntos e as coleções anteriores são que, ao contrário de listas e tuplas, - -1. conjuntos não retornam repetições. - -```py -valores = [1, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5] # lista -print(valores) - -valores = tuple(valores) # tupla -print(valores) - -valores = set(valores) # conjunto -print(valores) -``` -```textfile -[1, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5] -(1, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5) -{1, 2, 3, 4, 5} -``` - -2. conjuntos não permitem indexação. - -```py -print(valores[1]) -``` -```textfile ---------------------------------------------------------------------------- -TypeError Traceback (most recent call last) -Cell In[21], line 1 -----> 1 print(valores[1]) - -TypeError: 'set' object is not subscriptable -``` - -Com essas peculiaridades, é comum haver conversões de listas para conjuntos e, de novo, para listas: imagine que temos uma lista com 30 valores, e queremos (1) reordená-los do maior para o menor, (2) excluindo valores duplicados, e (3) encontrar os valores que estão nas posições 3 a 5. - -Sabemos que exclusão de duplicatas pode ser feita com conjuntos, e não com listas; sabemos que reordenação e indexação podem ser executadas com listas, e não com conjuntos. Então... - -```py -nums = [ - 7, 1, 5, 3, 3, 4, 9, 5, 3, 1, - 8, 9, 1, 1, 8, 5, 5, 7, 2, 6, - 5, 4, 7, 1, 6, 3, 2, 3, 1, 9, -] -print(nums) - -nums = set(nums) # com conjunto, excluo duplicatas... -print(nums) - -nums = list(nums) # ...aí converto de volta para lista... -print(nums) - -nums.sort(reverse=True) # ...e, na lista, reordeno do maior para o menor... -print(nums) - -print(nums[3:6]) # ...para buscar valores por indexação -``` -```textfile -[7, 1, 5, 3, 3, 4, 9, 5, 3, 1, 8, 9, 1, 1, 8, 5, 5, 7, 2, 6, 5, 4, 7, 1, 6, 3, 2, 3, 1, 9] -{1, 2, 3, 4, 5, 6, 7, 8, 9} -[1, 2, 3, 4, 5, 6, 7, 8, 9] -[9, 8, 7, 6, 5, 4, 3, 2, 1] -[6, 5, 4] -``` - -{{< warning >}} -No exemplo acima, usamos dois comandos para converter a lista em conjunto e, em seguida, em lista novamente: - -```py -nums = set(nums) -nums = list(nums) -``` -Podemos fazer isso numa linha só, de maneira encadeada: - -```py -nums = list(set(nums)) -``` -{{< /warning >}} -{{< /expandable >}} -{{< expandable label="Coleções de dados: dicionário" level="2" >}} -anteriormente vimos três coleções de dados: __lista__, __tupla__ e __conjunto__. Apenas para recapitular suas características: - -| lista | tupla | conjunto | -| :-: | :-: | :-: | -| exemplo: `x = [1, 2, 3, 4]` | exemplo: `y = (1, 2, 3, 4)` | exemplo: `z = {1, 2, 3, 4}` | -| uso de `[` e `]` | uso de `(` e `)` | uso de `{` e `}` | -| `list()` para lista vazia ou conversão | `tuple()` para tupla vazia ou conversão | `set()` para conjunto vazio ou conversão | -| aceita itens repetidos | aceita itens repetidos | aceita itens repetidos, mas retorna itens únicos | -| é mutável | é imutável | é imutável | -| aceita métodos para manipulação | não aceita métodos para manipulação | não aceita métodos para manipulação | -| itens acessados a partir da posição | itens acessados a partir da posição | itens inacessíveis a partir da posição | - -Além dessas três coleções, há outra muito importante: dicionário. Ao contrário das demais, um dicionário não tem apenas valor, mas também tem chave. Aliás, os itens de um dicionário são `sempre em pares chave-valor.` Por exemplo: - -```py -prof = {"nome": "Rodolfo"} -``` - -Repare na sintaxe de um dicionário: `{chave: valor}`. Portanto, um dicionário é feito de `{` e `}`, além de `:`, que é o que separa a chave —no exemplo, `"nome"`— do valor —`"Rodolfo"`. Para criá-lo eu também posso usar a função `dict()`. Vamos ver um exemplo: - -```py -curso = {"instituicao": "IDP"} -print(curso) -print(type(curso)) -``` -```textfile -{'instituicao': 'IDP'} - -``` - -Isso muda bastante a forma de trabalharmos com coleções: se antes o usual era ter listas ou tuplas com dados de um mesmo tipo... - -```py -frutas = ["maçã", "laranja", "banana"] -precos = [1.45, 2.07, 3.99] -``` -...agora podemos ter uma coleção com diversos tipos de dados... - -```py -frutas = {"produto": "maçã", "preco": 1.45} # a vírgula separa os pares chave-valor -``` -...ou até mesmo uma coleção de coleções, como lista de dicionários (algo bem comum, aliás). -```py -frutas = [ - {"produto": "maçã", "preco": 1.45}, - {"produto": "laranja", "preco": 2.07}, - {"produto": "banana", "preco": 3.99} -] -``` - -Vou fazer o meu perfil usando dicionário e os mais variados tipos de dados: - -```py -prof = { - "nome": "Rodolfo", - "sobrenome": "Viana", - "idade": 43, - "domicilio": "Marília, SP", - "tem_pet": True, - "qtde_pet": 1, - "nome_pet": "Pitoco", - "peso_pet": 11.5 -} - -print(prof) -print(f"Tenho {len(prof)} elementos numa única variável!") -``` -```textfile -{'nome': 'Rodolfo', 'sobrenome': 'Viana', 'idade': 43, 'domicilio': 'Marília, SP', 'tem_pet': True, 'qtde_pet': 1, 'nome_pet': 'Pitoco', 'peso_pet': 11.5} -Tenho 8 elementos numa única variável! -``` - -Mas agora que temos a estrutura chave-valor, como localizar um valor? Ou adicionar outro? Simples: basta usar a chave entre `[]`! - -```py -print(prof) # tenho o dicionário todo... -print(prof["tem_pet"]) #... e aqui, apenas o valor da chave "tem_pet" -``` -```textfile -{'nome': 'Rodolfo', 'sobrenome': 'Viana', 'idade': 43, 'domicilio': 'Marília, SP', 'tem_pet': True, 'qtde_pet': 1, 'nome_pet': 'Pitoco', 'peso_pet': 11.5} -True -``` -```py -print(f'{prof["nome"]} tem {prof["idade"]} anos e mora em {prof["domicilio"]}') -``` -```textfile -Rodolfo tem 43 anos e mora em Marília, SP -``` -Para adicionar um par chave-valor que não existe, funciona assim: - -``` -variavel["novachave"] = "novovalor" -``` -Vamos ver na prática: - -```py -print(prof) # repare que não tenho chave "signo"... -prof["signo"] = "Peixes" # ...mas eu a adiciono, e com o valor "Peixes"... -print(prof) # e o dicionário é atualizado -``` -```textfile -{'nome': 'Rodolfo', 'sobrenome': 'Viana', 'idade': 43, -'domicilio': 'Marília, SP', 'tem_pet': True, 'qtde_pet': 1, -'nome_pet': 'Pitoco', 'peso_pet': 11.5} -{'nome': 'Rodolfo', 'sobrenome': 'Viana', 'idade': 43, -'domicilio': 'Marília, SP', 'tem_pet': True, 'qtde_pet': 1, -'nome_pet': 'Pitoco', 'peso_pet': 11.5, 'signo': 'Peixes'} -``` -{{< /expandable >}} -{{< expandable label="Iteração com `for` - parte 1" level="2" >}} -Agora que conhecemos coleções de dados, podemos imaginar: - -> E se o programador quiser realizar a mesma operação para cada item da coleção? Deve escrever tudo de novo? - -A resposta é: não. Podemos usar controle de fluxo com `for` (ou `for` loop, como é conhecido). - -O `for` loop itera (ou seja, repete) a operação ou o comando para cada item da coleção. Sua sintaxe é assim: - -``` -for elemento in colecao: - operacao -``` -Seria como dizer em português: "para cada elemento de `colecao`, faça determinada `operacao`". Em desenho, - - - -Por exemplo, quero aumentar os preços da minha loja em 15% —e aqui, vamos usar também a função `round(x, quantidade_de_casas_decimais)`, que arredonda o valor de `x` estabelecendo determinada quantidade de casas decimais: - -```py -precos_atuais = [8.77, 9.12, 10.09, 6.71] # lista de preços atuais -precos_novos = list() # lista vazia que conterá os preços novos -percentual_aumento = 0.15 # percentual de aumento - -for i in precos_atuais: # para cada item (apelidado de i) na lista `precos_atuais`... - novo_valor = round(i + (i * percentual_aumento), 2) # ...calculo o novo valor... - precos_novos.append(novo_valor) # ...e adiciono o novo valor na lista `precos_novos` - -print(precos_novos) -``` -```textfile -[10.09, 10.49, 11.6, 7.72] -``` - -É possível ordenar ao sistema que realize qualquer operação, como passar uma lista de nomes, pedir as primeiras duas letras de cada nome e converter para letra minúscula com `lower()`... - -```py -nomes = ["José", "Manuel", "Carlos"] - -for x in nomes: - primeiras_letras = x[0:2] - print(primeiras_letras.lower()) -``` -```textfile -jo -ma -ca -``` - -...ou pedir ao usuário três números, salvá-los numa lista e pedir ao sistema que, para cada número, imprima se é par ou ímpar. - -```py -lista_nums = list() - -while len(lista_nums) < 3: - num = int(input("Digite um número inteiro: ")) - lista_nums.append(num) - -for x in lista_nums: - if x % 2 == 0: - print("É par") - else: - print("É ímpar") -``` -```textfile -Digite um número inteiro: 786 -Digite um número inteiro: 955 -Digite um número inteiro: 1205 -É par -É ímpar -É ímpar -``` - -{{< warning >}} -Nos exemplos acima, `x` aparece duas vezes: primeiro em... - -``` -for x in nomes: -``` - -...e depois, em... -``` -for x in lista_nums: -``` - -Afinal, o que é esse `x`? - -É, digamos, uma "variável temporária". É o nome que damos para o item da coleção que está sendo processado no momento —ou seja, as operações serão feitas em cima da "variável temporária". Quando o item termina de ser processado, a "variável temporária" é atribuída ao próximo item da coleção, e assim sucessivamente. - -E não precisa ser `x`! Pode ser qualquer letra, nome etc. Vamos ver um exemplo: - -```py -lista_exemplo = ["André", "Regina", "Fernanda", "Pedro"] -contador = 0 -# eu uso `nome` como variável temporária para o item... -for nome in lista_exemplo: - contador += 1 - # ...e faço operação com essa variável temporária - print(f"No {contador}º loop, a 'variável temporária' `nome` é {nome}") -``` -```textfile -No 1º loop, a 'variável temporária' `nome` é André -No 2º loop, a 'variável temporária' `nome` é Regina -No 3º loop, a 'variável temporária' `nome` é Fernanda -No 4º loop, a 'variável temporária' `nome` é Pedro -``` -{{< /warning >}} - -Aqui, um exemplo uso de `for` loop no contexto de jornalismo de dados: numa série de reportagens na TV Globo sobre o retrato da mobilidade em São Paulo —projeto "Anda SP"—, tínhamos uma pesquisa com diversas informações sobre os entrevistados, todos ciclistas, como idade. Precisávamos agrupar essas pessoas em categorias de acordo com a faixa etária. A lógica era: - -1. do arquivo `csv` a que tínhamos, eu precisava de ver linha a linha o campo `IDADE`; - - ou seja, uso de `for` loop -2. e, dependendo do valor no campo, descrever o grupo ao qual pertencia - - ou seja, uso de condicionais com `if` - -Então a operação foi esta: - -```py -# Segregação por faixa etária -fx_et = [] -for row in bike_limpo['IDADE']: - if row < 18: - fx_et.append('Menor de 18 anos') - elif row >= 18 and row < 25: - fx_et.append('18 a 24 anos') - elif row >= 25 and row < 31: - fx_et.append('25 a 30 anos') - elif row >= 31 and row < 41: - fx_et.append('31 a 40 anos') - elif row >= 41 and row < 51: - fx_et.append('41 a 50 anos') - elif row >= 51 and row < 61: - fx_et.append('51 a 60 anos') - else: - fx_et.append('61 anos ou mais') -``` - -Aqui, o estudo na íntegra: [2019-06-28-od_bicicleta](https://github.com/rodolfo-viana/ddj_stuff/blob/main/ipynb/2019-06-28-od_bicicleta.ipynb). -{{< /expandable >}} -{{< expandable label="Iteração com `for` - parte 2" level="2" >}} -Anteriormente vimos como `for` loop funciona com listas, tuplas... Recapitulando: - -```py -nums_gerais = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -nums_pares = list() - -for i in nums_gerais: # para cada item de `nums_gerais... - if i % 2 = 0: # ...o item dividido por 2 tiver como resto 0... - nums_pares.append(i) # ...adicione o item na lista `nums_pares` - -print(nums_pares) -``` -```textfile -[2, 4, 6, 8, 10] -``` - -Outro exemplo: - -```py -cidades = ["São Paulo", "Brasília", "Rio de Janeiro", "Curitiba", "Salvador"] -trecho = list() - -for c in cidades: - if c in ["São Paulo", "Rio de Janeiro"]: - trecho.append("Eixo Rio-São Paulo") - else: - trecho.append("Fora do eixo Rio-São Paulo") - -print(trecho) -``` -```textfile -['Eixo Rio-São Paulo', 'Fora do eixo Rio-São Paulo', 'Eixo Rio-São Paulo', -'Fora do eixo Rio-São Paulo', 'Fora do eixo Rio-São Paulo'] -``` - -O `for` loop —que permite a iteração (repetição) de determinada operação para cada elemento de uma coleção— é algo simples de compreender, mas diferente quando trabalhamos com __dicionários__. Isso porque dicionários, como sabemos, é feito de __par chave-valor__. Veja que interessante: - -```py -lista = ["Cachorro", "Gato", "Passarinho"] - -for a in lista: - print(a) -``` -```textfile -Cachorro -Gato -Passarinho -``` -```py -dicionario = {"animal_1": "Cachorro", "animal_2": "Gato", "animal_3": "Passarinho"} - -for a in dicionario: - print(a) -``` -```textfile -animal_1 -animal_2 -animal_3 -``` - -Quando fazemos `for` loop "convencional" em dicionário, ele retorna somente as chaves, e não os valores. Isso porque, na construção do `for` loop, eu pedi apenas um elemento, na linha: - -``` -for a in dicionario: -# pedi apenas `a` -``` - -Como dicionário é feito de par chave-valor, eu preciso pedir dois elementos —um para a chave, outro para o valor. E também usar `.items()`, para indicar ao sistema para procurar dentro dos itens. Algo assim: - -``` -for a, b in dicionario.items(): -# pedi `a` para chave, `b` para valor dentro dos itens -``` - -Vamos testar com o exemplo: - -```py -dicionario = {"animal_1": "Cachorro", "animal_2": "Gato", "animal_3": "Passarinho"} - -for a, b in dicionario.items(): # `a` para chave, `b` para valor - print(f"A chave {a} tem o valor {b}") -``` -```textfile -A chave animal_1 tem o valor Cachorro -A chave animal_2 tem o valor Gato -A chave animal_3 tem o valor Passarinho -``` - -Trabalhar com chaves e valores abre inúmeras possibilidades de análise. Por exemplo: - -```py -precos = {"banana": 1.49, "maçã": 1.79, "mamão": 2.15} -print('Preços originais:', precos) - -# Quero aumentar os preços de todos os produtos em 10% -for k, v in precos.items(): - precos[k] = round(v * 1.1, 2) # 1.1 porque 10% é 1 + 0.1 - -print(precos) -print('Preços ajustados (10% de aumento):', precos) - -# Quero reduzir em 5% o preço do mamão -for k, v in precos.items(): - if k == "mamão": - precos[k] = round(v * 0.95, 2) - -print('Preços ajustados (10% de aumento; -5% se for mamão:', precos) -``` -```textfile -Preços originais: {'banana': 1.49, 'maçã': 1.79, 'mamão': 2.15} -Preços ajustados (10% de aumento): {'banana': 1.64, 'maçã': 1.97, 'mamão': 2.37} -Preços ajustados (10% de aumento; -5% se for mamão): {'banana': 1.64, 'maçã': 1.97, 'mamão': 2.25} -``` -{{< /expandable >}} -{{< expandable label="Funções" level="2" >}} -Seja com `for` loop ou `if`-`else`; seja com coleções ou não, estamos sempre fazendo uma ou mais operações em Python. Por exemplo: - -```py -salario = 2500 # operação 1 -despesa = 1875 # operação 2 - -if salario > despesa: # operação 3 - calculo = salario - despesa # operação 4 - print(f"Sobram-me {calculo} reais.") # operação 5 -elif salario < despesa: # operação 6 - calculo = despesa - salario # operação 7 - print(f"Faltam-me {calculo} reais.") # operação 8 -else: # operação 9 - print("Salário e despesas têm o mesmo valor. Não me sobra nada.") # operação 10 -``` - -Chamamos essas operações encadeadas de rotinas. Muitas vezes, queremos repetir uma rotina: - -```py -lista_1 = [2.35, 6.78, 12.07] -lista_2 = [1.15, 9.78, 10.12] - -for n in lista_1: - calculo = 2 * n - print(calculo) - -for n in lista_2: - calculo = 2 * n - print(calculo) -``` - -No exemplo acima, repare que tenho duas listas distintas (`lista_1` e `lista_2`), e para cada faço a mesma rotina: - -1. faço `for` loop, -2. faço o cálculo de multiplicação por 2 -3. imprimo o valor do cálculo - -__Simplesmente repito o código__, linha a linha! - -Para evitar repetições, podemos contar com __funções__. Funções são rotinas que têm um nome e ficam temporariamente salvas na sua máquina. São sequências de operações determinadas pelo programador que podem ser usadas sempre que necessárias. - -Python tem várias funções prontas, muitas das quais já vimos nas aulas: `bool()`, `dict()`, `float()`, `format()`, `input()`, `int()`, `len()`, `print()`, `round()`, `set()`, `str()`, `tuple()`, `type()`... E há ainda outras tantas, que podem ser vistas [neste link](https://docs.python.org/pt-br/3.11/library/functions.html). Mas além das funções prontas, podemos criar as nossas próprias! A sintaxe para definir uma função é assim: - -``` -def nomedafuncao(): - operacao -``` - -E a sintaxe para chamar (usar) uma função é assim: - -``` -nomedafuncao() -``` - -Por exemplo, uma função que: - -1. pergunta o nome do usuário, -2. deixa todas as letras em caixa alta, -3. imprime "Bom dia", acompanhado do nome do usuário. - -```py -def bomdia(): # defino o nome da minha função - nome = input("Qual o seu nome? ") # operação 1: pedir o nome - nome = nome.upper() # operação 2: deixar o nome em caixa alta - print(f"Bom dia, {nome}") # operação 3: imprimir a frase - -bomdia() # chamo a função... -``` -```textfile -Qual o seu nome? Rodolfo -Bom dia, RODOLFO -``` -```py -bomdia() # ...de novo... -``` -```textfile -Qual o seu nome? André -Bom dia, ANDRÉ -``` -```py -bomdia() # ...e de novo, sem precisar reescrever as operações definidas -``` -```textfile -Qual o seu nome? Ana Maria -Bom dia, ANA MARIA -``` - -Com o exemplos das listas, poderíamos usar uma função. Assim: - -```py -def multiplicar(): - calculo = 2 * n - print(calculo) - -lista_1 = [2.35, 6.78, 12.07] -lista_2 = [1.15, 9.78, 10.12] - -for n in lista_1: - multiplicar() - -for n in lista_2: - multiplicar() -``` -```textfile -4.7 -13.56 -24.14 -2.3 -19.56 -20.24 -``` - -### Argumentos - -No exemplo acima, criei uma função para multiplicar por 2. Mas e se eu quiser multiplicar por 3 ou por 6 ou por 127? E se o número multiplicador for dinâmico? - -Para isso contamos com parâmetros e argumentos. - -- __Parâmetro__ é o nome dado ao atributo que uma função pode receber - -- __Argumento__ é o valor recebido pela função - -A sintaxe para criar uma função com parâmetro é assim: - -``` -def nomedafuncao(parametro): - bloco de código, rotina que usa o parâmetro -``` - -E a sintaxe para chamar a função é: - -``` -nomedafuncao(argumento) -``` - -Vamos refazer o exemplo de multiplicação, mas com parâmetros e argumentos: - -```py -def multiplicar(n_mult): # `n_mult` é o parâmetro... - calculo = n_mult * n # ...que é usado no bloco da rotina - print(calculo) - -lista_1 = [2.35, 6.78, 12.07] -lista_2 = [1.15, 9.78, 10.12] - -for n in lista_1: - multiplicar(6) # o argumento `6` entra no lugar do parâmetro `n_mult` - -for n in lista_2: - multiplicar(127) # o número 127 é o argumento -``` -```textfile -14.100000000000001 -40.68 -72.42 -146.04999999999998 -1242.06 -1285.24 -``` - -Posso usar quantos parâmetros e argumentos eu quiser, do tipo que eu quiser. - -```py -def multiplicar(lista, multiplicador): # tenho dois parâmetros... - for i in lista: - calculo = multiplicador * i - print(calculo) - -lista_1 = [3.89, 0.99, 17.15, 1.89] - -multiplicar(lista_1, 7) # ...e uso dois argumentos -``` -```textfile -27.23 -6.93 -120.04999999999998 -13.229999999999999 -``` - -Mas se eu passar um parâmetro e ele não tiver argumento, ou se eu usar um argumento sem parâmetro, encontro erro: - -```py -def multiplicar(lista, multiplicador): # tenho dois parâmetros... - for i in lista: - calculo = multiplicador * i - print(calculo) - -lista_1 = [3.89, 0.99, 17.15, 1.89] - -multiplicar(lista_1) # ...e uso apenas um argumento -``` -```textfile ---------------------------------------------------------------------------- -TypeError Traceback (most recent call last) -Cell In[10], line 1 -----> 1 multiplicar(lista_1) # ...e uso apenas um argumento - -TypeError: multiplicar() missing 1 required positional argument: 'multiplicador' -``` - -```py -multiplicar(lista_1, 7, 9) # ...e uso três argumentos -``` -```textfile ---------------------------------------------------------------------------- -TypeError Traceback (most recent call last) -Cell In[11], line 1 -----> 1 multiplicar(lista_1, 7, 9) # ...e uso três argumentos - -TypeError: multiplicar() takes 2 positional arguments but 3 were given -``` - -### `return` vs. `print` - -Vimos até aqui que `print()` é a função que usamos para imprimir algo na tela. Contudo, nem sempre queremos imprimir algo, mas sim salvar o resultado da função na memória para uso posterior. Nesse caso usamos, dentro da função, `return`. Vamos ver um exemplo: - -Preciso calcular o volume de um cilindro (fórmula: \\(V = \pi r^2 h\\), onde \\(r\\) é o raio; \\(h\\) é a altura). Com o volume, preciso calcular o preço, sendo R$ 1,50 para cada unidade de volume. (Repare: eu não quero imprimir o volume; quero usá-lo para operações futuras —no caso, calcular o valor total.) - -```py -# crio uma função para determinar o volume de um cilindro -def volume(r, h): - pi = 3.14159 - vol = pi * r**2 * h - return vol # uso `return` no final, com o dado que quero obter - -# crio outra função, para calcular o valor -def valor(volume): - vlr_unit = 1.5 - vlr_final = volume * vlr_unit - return vlr_final - - -# calculo o volume usando a função que criei -# o resultado ficará armazenado em `cilindro_1` -cilindro_1 = volume(16, 3) - -# agora uso `cilindro_1` para calcular o valor -# o resultado ficará armazenado em `valor_1` -valor_1 = valor(cilindro_1) - -# reuso a função -cilindro_2 = volume(13, 6) -valor_2 = valor(cilindro_2) - -# até aqui, nada é impresso na tela, pois não usei `print()`, -# mas sim `return`, para devolver o resultado das operações -# em uma variável - -# só aqui imprimo -print(valor_1) -print(valor_2) -``` -```textfile -3619.1116799999995 -4778.358389999999 -``` - -Um exemplo de como funções são usadas no jornalismo de dados é este código escrito pela equipe do FiveThirtyEight para obter dados metereológicos do site Weather Underground. A reportagem em que tais dados foram usados é esta: ["What 12 Months Of Record-Setting Temperatures Looks Like Across The U.S."](https://fivethirtyeight.com/features/what-12-months-of-record-setting-temperatures-looks-like-across-the-u-s/). O código na íntegra está [aqui](https://github.com/fivethirtyeight/data/blob/76c471a9124d690ba92709ca21cbfcdde226b44e/us-weather-history/wunderground_scraper.py), mas abaixo segue uma versão editada e comentada para melhor compreensão: - -```py -# importação de módulos para... -from datetime import datetime, timedelta # ...trabalhar com datas -from urllib.request import urlopen # ...abrir sites - - -def scrape_station(station): # parâmetro é `station` - current_date = datetime(year=2014, month=7, day=1) # data atual - end_date = datetime(year=2015, month=7, day=1) # data final - lookup_URL = 'http://www.wunderground.com/history/airport/{}/{}/{}/{}/DailyHistory.html' - - while current_date != end_date: # enquanto a data atual é diferente da data final... - formatted_lookup_URL = lookup_URL.format( - station, current_date.year, current_date.month, current_date.day - ) # ...formate `lookup_URL` - html = urlopen(formatted_lookup_URL).read().decode('utf-8') # ...abra e leia o site - current_date += timedelta(days=1) # ...adicione `1` dia na data atual - -# para cada uma das estações na lista... -for station in ['KCLT', 'KCQT', 'KHOU', 'KIND', 'KJAX', 'KMDW', 'KNYC', 'KPHL', 'KPHX', 'KSEA']: - # ...execute a função para cada estação - scrape_station(station) -``` -{{< /expandable >}} \ No newline at end of file