Variáveis e tipos de dados¶

Para salvar um dado durante uma seção, criamos uma variável. Uma variável é definida digitando-se seu nome seguido do operador de atribuição = e do dado a ser atribuído a ela. Por exemplo, o código

a = 1

cria uma variável contendo o valor 1. Variáveis possuem tipos básicos que correspondem à forma como são tratadas e armazenadas na memório do computados. Você pode pedir par o Python informar o tipo de uma variável usando o comando type.

Para exibir o valor de uma variáve, usamos a função print, como no exemplo abaixo:

print(a)

Para imprimir a variável a e a variável b, separadas por um espaço digite

print(a, b)

Exemplos:

In [1]:
# Tipos numéricos:

nint = 102
print(type(nint))
<class 'int'>
In [2]:
nfloat = 20.2 # Exemplo de um número de ponto flutuante (float)
print(type(nfloat))
<class 'float'>
In [3]:
ncomplex_1 = 3 + 4j # Cria um número complexo com parte real igual a 3 e parte imaginária igual a 4
ncomplex_2 = complex(3, 4) # Idem, porém usando a função complex
print(ncomplex_1)
print(ncomplex_2)
print(type(ncomplex_1))
print(type(ncomplex_2))
(3+4j)
(3+4j)
<class 'complex'>
<class 'complex'>

Operações com tipos numéricos¶

Operação Resultado
$x + y$ soma de x e y
$x - y$ diferença de x e y
$x * y$ produto de x vezes y
$x / y$ quociente de x por y
$x // y$ divisão inteira de x por y
$x \% y$ resto de x por y
$x ** y$ x elevado a y

O Python tenta realizar operações entre dados numéricos de tipos diferentes, promovendo o tipo mais restritivo para o tipo menos restritivo:

Inteiro -> Float -> Complex

Tipo lógico (bool)¶

Trata-se de um tipo que pode assumir apenas dois valores: True e False. Frequentemente, resulta de um teste lógico

Exemplo: comparação de tipos numéricos

In [4]:
a = 1; b = 2.2 # atribui 1 à variável a e 2.2 à variável b
print(a == b) #testa se a é igual a b (note que, para a comparaçào, usamos ==, visto que "=" é o operador de atribuição)
print(a > b) # testa se a é maior do que b
print(a >= b) # testa se a é maior ou igual a b
print(a <= b) # testa se a é menor ou igual a b
print(a != b) # testa se a é diferente de b
print(ncomplex_1==ncomplex_2) # testa se n_complex_1 é igual a n_complex_2
False
False
False
True
True
True

Instrução condicional¶

O python entende instruções com a forma

if [condição 1]:
    [instruções 1]
elif [condição 2]:
    [instruções 2]
elif [condição 3]:
    [instruções 3]
...
elif [condição n-1]:
    [instruções n-1]
else:
    [instruções n]

Na qual [condição 1], [condição 2], ..., [condição n-1] são expressões que retornam um valor lógico. O código acima faz com que o python execute o grupo de instruções [instruções j], se e somente se, $j=0$ ou, para todo inteiro $i$ tal que $1 \le i < j$, a expressão [condição i] retorne o valor False.

Exemplo:

In [5]:
a = 110.
b = 104

if a < b:
    print("a é menor do que b")
elif a == b:
    print("a é igual a b")
else:
    print("a é maior do que b")
    
    
print("Pronto!")
a é maior do que b
Pronto!

Funções¶

Imagine que você estaja fazendo um trabalho que requeira que você calcule a soma dos quadrados dos primeiros $n$ números naturais para diferentes valores de $n$. Depois de pesquisar, você essa soma é dada pela fórmula.

$$ S_n = \frac{n (n + 1) (2n + 1)}{6} $$

Conforme, dissemos, você terá que calcular essa fórmula para diferentes valores de $n$. Imagine que o primeiro desses valores fosse $n=3$. Então, você poderia escrever o código:

In [6]:
n = 3
s = n * (n + 1) * (2 * n + 1) / 6

para salvar a soma dos quadrados dos inteiros de 1 até $n$ na variável s. Se, agora, $n$ assumisse um outro valor, você poderia reaproveitar o código acima, simplesmente trocando n = 3 por n = 5. Isso funcionaria, mas parece ser um trabalho desnecessariamente repetitivo. Para evitar esse tipo de repetição, você pode escrever um pequeno programa, usando a função input. Abra um editor de text e, em um novo arquivo, escreva o seguinte código:

mnsgm = 'Entre a quantidade dos primeiros quadrados a serem somados'
n = int(input(mnsgm))
s = n * (n + 1) * (2 * n + 1) // 6
print(s)

A primeira linha cria uma mensagem. Essa mensagem é usada, na segunda linha, como argumento da função input que imprime seu argumento, a mensagem, e solicita ao usuário que digite alguma informação, no caso, o número $n$, e retorna o que o usuário digitar como um objeto de texto. Para converter o que for informado em um número inteiro, colocamos a função input como argumento da função int. Assim, o valor de n, informado pelo usuário será armazenado, como um número inteiro, na variável n.

A terceira linha calcula a soma dos primeiros $n$ quadrados e, a quarta linha imprime o resultao.

Salve o ser arquivo como o nome soma_quadrados.pye em um console, no mesmo diretório em que salvou seu arquivo, escreva o comando

python soma_quadrados.py

Se você fez tudo corretamente, receberá uma mensagem para informa o valor de $n$, e, após isso, o valor da soma dos primeiros $n$ quadrados.

Porém, o procedimento acima é limitado e não atende ao caso mais provável que seria aquele no qual você gostaria de calcular em uma mesma sessão do python, ou em um mesmo script, a somas dos primeiros quadrados diversas vezes. Para esse caso, definimos uma função. A declaração de uma função tem a forma:

def nome(argumentos):
    '''Descrição.'''
    instruções

na qual nome é o nome que você escolheu para a função, argumentos é uma série zero ou mais nomes de variáveis que assumirão os valores a sere informados quando a função for chamada, Descrição é um texto opcional contendo descrição ou documentação da função e, intruções é o código a ser executado sempre que a função for chamada.

Note que tanto a descrição quanto o código estão identados. Isso é obrigatório.

Abaixo, um código que define uma função que calcula a soma dos primeiros $n$ quadrados em que $n$ é o argumento da função.

In [7]:
#criação da função:
def soma_quadrados(n):
    s = n * (n + 1) * (2 * n + 1) // 6
    return s


# Testes da função
print(soma_quadrados(7))

print(soma_quadrados(20))
140
2870

Loop While¶

Se você não souber a fórmula, pode usar um loop para somar todos os quadrados. Na verdade, vamos ver daqui a pouco que esse procedimento pode, muitas vezes ser evitado quando se usa o Python. Para tal, usaremos a instrução while do Python. Essa instrução é um tipo de loop. Um loop é qualquer procedimento que é repetido inumeras vezes até que determinada condição, expressa por meio de um teste lógico, seja atendida. No caso do loop while, a repetição é feita enquanto o teste lógico, digitado logo após a instrução while for verdadeiro. A sintaxe da instrução while é

while condição:
    instruçòes

na qual condição deve ser substituída por uma expressão que retorne um booleano, ou algo que possa ser interpretado pelo Python como booleano e instruções é o conjunto de instruções a serem repetidas no loop while. Note que, após condição você deve, necessariamente, acrescentar dois pontos (:) e, se as intruções a serem executadas forem digitadas a partir da linha seguinte à da instrução while, elas deve aparecer identadas. Usando a instrução while, podemos escrever uma nova função para calcular a soma dos primeiros quadrados, conforme se segue:

In [8]:
def soma_quadrados_2(n):
    i = 0
    s = 0
    while i < n:
        i += 1
        s += i ** 2
        
    return s


print(soma_quadrados_2(7))

print(soma_quadrados_2(20))
140
2870

Tipos de sequências: listas (list), tuplas (tuple) e intervalo (range) e tipo texto (string)¶

Uma outra instrução do Python que gera um loop é a instrução for. Para entender essa intrução, precisamos falar de um novo conjunto de objetos do Pythos que são os objetos tipo sequência. Tratam-se de objetos que são uma coleção ordenada de outros objetos. Por coleção ordenada quero dizer aqui, uma coleção tal cada um de seus elemento é associado a um e apenas um dos números naturais entre 1 e o número de elementos da coleção.

Tipo list¶

O tipo list de um tipo de sequencia de dados modificável. É definido colocando entre colchetes os valores a serem armazenados separados por vírgula. Exemplos

In [9]:
nomes = ["Mariana", "João", "Pedro", "Julia", "Renata", "Diego", "Sofia", "Ricardo"]
prova_1 = [4, 4.6, 5.2, 3.9, 6.3, 2.2, 5.2, 5.0]
prova_2 = [10, 8.0, 9.3, 1, 7, 5.2, 1, 6.9]
In [10]:
print(nomes[0])
print(prova_1[2])
print(prova_2[7])
Mariana
5.2
6.9
In [11]:
print(nomes[-1])
print(prova_1[-4])
Ricardo
6.3

Fatias¶

Se quiser selecionar os elementos de uma lista com índices em um intervalo entre i e j, use

nome_lista[i:j]

Os dois pontos : são chamados de um operador de fatiamento (slicing operator). A operação i:j, resulta em uma fatia.

In [12]:
print(nomes[2:6])
['Pedro', 'Julia', 'Renata', 'Diego']

: é chamado operador de fatiamento (slicing operator). O resultado de i:j é chamado de uma fatia (slice). O operador de fatiamento pode ser usado de diversos modos:

Para obter uma fatia de uma lista contendo os elementos com índices de $i$ até $j-1$, use nome_lista[i:j]

In [13]:
print(nomes)
print(nomes[3:8])
['Mariana', 'João', 'Pedro', 'Julia', 'Renata', 'Diego', 'Sofia', 'Ricardo']
['Julia', 'Renata', 'Diego', 'Sofia', 'Ricardo']

Para obter uma fatia de uma lista contendo os elemento com índices $i$ até $j-1$, selecionados a cada $k$ elementos, use

nome_lista[i:j:k]
In [14]:
nomes[3:8:2]
Out[14]:
['Julia', 'Diego', 'Ricardo']

:j fatia todos os elementos da lista até o elemento de ordem $j-1$;

i: fatia todos os elemento da lista desde o elemento $i$;

:j:k fatia todos os elementos da lista com índices $nk$, com $n$ inteiro, desde que $0 \le n \le \frac{j}{n}$;

i::k fatia todos os elementos da lista com índices $i + nk$, com $n$ inteiro, $n\ge 0$;

::k fatia os elementos na lista com índices $nk$, $n =0, 1, \dots$.

In [15]:
print(nomes)
['Mariana', 'João', 'Pedro', 'Julia', 'Renata', 'Diego', 'Sofia', 'Ricardo']
In [16]:
print(nomes[:4])
['Mariana', 'João', 'Pedro', 'Julia']
In [17]:
print(nomes[4:])
['Renata', 'Diego', 'Sofia', 'Ricardo']
In [18]:
print(nomes[:4:2])
['Mariana', 'Pedro']
In [19]:
print(nomes[:4:3])
['Mariana', 'Julia']
In [20]:
print(nomes[4::2])
['Renata', 'Sofia']
In [21]:
print(nomes[::3])
['Mariana', 'Julia', 'Sofia']

Você pode usar passos negativos na definição da fatia:

In [22]:
print(nomes)
print(nomes[7:3:-1])
['Mariana', 'João', 'Pedro', 'Julia', 'Renata', 'Diego', 'Sofia', 'Ricardo']
['Ricardo', 'Sofia', 'Diego', 'Renata']
In [23]:
print(nomes[-3::-2])
['Diego', 'Julia', 'João']
In [24]:
print(nomes[3:8:-1]) # Retornará uma lista vazia, pois somando-se -1 um a 3 sucessivamente não se chaga nunca a 8
[]
In [25]:
print(nomes[::-1]) # Retorna a lista de nomes em ordem inversa
['Ricardo', 'Sofia', 'Diego', 'Renata', 'Julia', 'Pedro', 'João', 'Mariana']
In [26]:
print(nomes[-2::-1]) # Retorna a lista de nomes até o penúltimo em ordem inversa
['Sofia', 'Diego', 'Renata', 'Julia', 'Pedro', 'João', 'Mariana']

Ao invés de usar o operador :, você pode usar a função

slice(i, j, k)
In [27]:
nomes[slice(0, -1, 2)] # nomes com índices pares
Out[27]:
['Mariana', 'Pedro', 'Renata', 'Sofia']
In [28]:
nomes[slice(1,-1,2)] # nomes com índices ímpares
Out[28]:
['João', 'Julia', 'Diego']

Listas com diferentes tipos de objetos¶

Uma lista pode conter objetos de tipos diferentes.

In [29]:
lista = [3, 5, 3, False]
print(type(lista[0]))
print(type(lista[-1]))
<class 'int'>
<class 'bool'>

Nada impede, inclusive, que os elementos de uma lista sejam outras listas:

In [30]:
lista_2 = [ [1, 2, 3], # primeiro elemento, a lista [1, 2, 3]
            [4, 5, 6], # segundo elemento, a lista [4, 5, 6]
            [7, 8, 9]  # terceiro elemento, a lista [7, 8, 9]
          ]
print(lista_2)
print(lista_2[1])
print(lista_2[1][1])
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[4, 5, 6]
5

Alterando objetos lists¶

Para modificar um elemento de um objeto list, use a expressão

list[i] = novo_valor
In [31]:
print(nomes[3])
nomes[3]="Júlia"
print(nomes[3])
Julia
Júlia

Se você tentar atribuir valor a um elemento com índice maior do o número de elementos da lista menos 1, o python retornará um erro.

Contando o número de elementos de uma lista¶

Use a função len (abreviação de length) para contar o número de elementos de uma lista, ou de qualquer objeto.

In [32]:
print(len(nomes))
8

Tuplas¶

Tuplas são objetos sequência imutáveis. Elas são definidas listanto seus elementos entre parênteses.

In [33]:
tupla_1 = (1, 2, 3)
print(tupla_1)
print(type(tupla_1))
(1, 2, 3)
<class 'tuple'>

Os parênteses são opcionais

In [34]:
tupla_2 = 4, 5, 6
print(tupla_2)
print(type(tupla_2))
(4, 5, 6)
<class 'tuple'>

Tuplas podem conter elementos de tipos diferentes, incluindo listas e outras tuplas:

In [35]:
tupla_3 = (tupla_1, tupla_2, nomes[1])
print(tupla_3)
((1, 2, 3), (4, 5, 6), 'João')

Tuplas são indexadas de modo similar às listas. Se a fatia contiver mais de um elemento, será retornada uma tupla. Se ele contiver apenas um elemento será retornado esse elemento.

In [36]:
subtupla_1 = tupla_1[::2]
print(subtupla_1)
print(type(subtupla_1))
(1, 3)
<class 'tuple'>
In [37]:
subtupla_1_b = tupla_1[2]
print(subtupla_1_b)
print(type(subtupla_1_b))
3
<class 'int'>

Se você tentar alterar uma tupla, o python retornará um erro.

Conversão entre tuplas e lists¶

Você pode converter tuplas em lists e vice-versa, basta usar as funções list e tuple

In [38]:
tpl_p_lst = list(tupla_1)
print(type(tpl_p_lst))
lst_p_tpl = tuple(tpl_p_lst)
print(type(lst_p_tpl))
<class 'list'>
<class 'tuple'>

Você pode usar tuplas para definir diversas variáveis em uma única linha. À esquerda do operador de atribuição colocamos uma tupla com as variáveis que queremos definir. À direita, colocamos os valores que queremos atribuir a essas variáveis. Por exemplo,

In [39]:
(x, y, z) = (12.2, 31.8, 97.43)
print(x)
print(y)
print(z)
12.2
31.8
97.43

Nesse caso é comum omitir os parênteses:

In [40]:
x, y, z = 12.2, 31.8, 97.43
print(x)
print(y)
print(z)
12.2
31.8
97.43

Objetos range¶

Um objeto range é uma sequência de números inteiros tais que a diferença entre dois números subsequentes é constante. Ele é definido usando a função range com a seguinte sintaxe:

range(começo, fim, passo)

na qual começo é o número inicial da sequência, fim é o menor inteiro maior que todos os números do objeto range, caso passo > 0, ou, caso passo < 0, o maior inteiro menor que todos os números do objeto e passo é a diferença entre elementos subsequentes da sequência. Por exemplo, a instrução abaixo cria um objeto range cujo elemento de ordem zero é 0, o de ordem 1 é 2, o de ordem 2 é 4 e o de ordem 3 é 6.

In [41]:
intervalo_1 = range(0, 7, 2)
intervalo_2 = range(1, -5, -1)

Porém quando você pede para o python imprimir um objeto range, ele não mostra os elementos desse objeto, mas sim os parâmetros que o definiram. Você pode contornar isso usando a função list ou a função tuple para converter o objeto range em um objeto list ou um objeto tuple, respectivamente.

In [42]:
print(intervalo_1)
print(list(intervalo_1))
print(tuple(intervalo_1))
print(list(intervalo_2))
print(tuple(intervalo_2))
range(0, 7, 2)
[0, 2, 4, 6]
(0, 2, 4, 6)
[1, 0, -1, -2, -3, -4]
(1, 0, -1, -2, -3, -4)

Você pode indexar um objeto range da mesma forma que indexa um objeto list ou um objeto tuple

In [43]:
print(intervalo_1[2])
print(intervalo_2[-2])
4
-3

Se você fornecer apenas dois argumentos para a função range, o python irá interpretar o primeiro argumento como o início, o segundo como o fim e irá assumir que passo = 1. Se você inserir apenas um argumento, ele tomará esse argumento como o fim e assumirá início = 0 e passo = 1.

In [44]:
print(list(range(5, 10)))
print(list(range(11)))
[5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Instrução for¶

Dois tipos de loops muito frequentes em todas as linguagens de programação são

a) loops que repetem as mesmas intruções para o valor de uma variável variando entre os primeiros $n$ números naturais e

b) loops que percorrem uma coleção de objetos, como, por exemplo, um objeto list, e perfazem a mesma operação em todos seus elementos.

No Python, assim como no R, esses loops são implementados por uma instrução for. O formato dessa instrução é

for variável in objeto:
    instruções

na qual objeto é um objeto iterável, variável é um nome escolhido para uma variável que assumirá, em cada ciclo do loop o valor de cada elemento do objeto e instruçòes é o conjunto de instruções que serão executadas em cada ciclo do loop.

Como exemplo, retomemos o problema de calcular a soma dos $n$ primeiros quadrados sem usar a fórmula dessa soma. Usando a instrução for, podemos escrever o seguinte código:

In [45]:
def soma_quadrados_3(n):
    s = 0
    for i in range(1, n + 1):
        s = s + i ** 2
    return(s)


print(soma_quadrados_3(5))
55

No caso em que o loop for é usado para criar uma lista, é possível usar uma sintaxe mais curta, conhecida com list comprehension. Ela tem a forma

[ expr(variável) for variável in objeto ]

na qual expr(variável) é uma expressão envolvendo o nome de uma variável criada para o loop e objeto é uma coleção iterável contento o conjunto de valores que a variável irá assumir. Por exemplo, para retornar uma lista com os $n$ primeiros quadrados, podemos escrever

In [46]:
n = 5
[ i ** 2 for i in range(1, n + 1) ]
Out[46]:
[1, 4, 9, 16, 25]

Podemos então redefinir nossa função soma quadrados usando uma notação mais enxuta:

In [47]:
def soma_quadrados_4(n):
    quadrados = [ i ** 2 for i in range(1, n + 1)]
    s = sum(quadrados)
    return s


soma_quadrados_4(5)
Out[47]:
55

As lists comprehension são muito frequentes em código python pois permitem uma escrita bem sintética sem comprometer a legibilidade do código. Porém, há situações em que elas não são aplicáveis.

Como exemplo, considere uma sequência de números inteiros $s_0, s_1, s_2, \dots$ tal que $s_0 = 0$, $s_1 = 1$ e, para qualquer $n > 1$, $s_n = s_{n-2} + s_{n-1}$. Essa sequência é conhecida como sequência de Fibonacci, ou sequência de números de Fibonacci. Seus elementos de 0 a 10 são

$0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55$

Podemos usar o loop for para criar duas funções. A primeira delas gera uma lista com os primeiros números de Fibonnaci até o número de ordem $n$. A segunda delas retorna o número de Fibonacci de ordem $n$.

In [48]:
def seq_fibonacci(n):
    if n == 0:
        s = [0]
    else:
        s = [0, 1]
    for i in range(2, n + 1):
        fi = s[-2] + s[-1]
        s.append(fi)
    return s
In [68]:
print(seq_fibonacci(10))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
In [48]:
def fibonacci(n):
    a, b = 0, 1
    for i in range(1, n + 1):
        a, b = b, a + b
    return a

print(seq_fibonacci(10))
print(fibonacci(10))
print(fibonacci(1000))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
55
43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875

Uma característica interessando do Python 3 é que, diferentemente do que ocorre no R e no Excel, ele é capaz de trabalhar com números inteiros com precisão ilimitada. Isso significa que você pode trabalhar com precisão absoluta com qualquer número inteiro desde que seu tamanho não exceda a capacidade de memória de seu computador.

A definição da função seq_fibonacci pode ser simplificada, conforme se segue

In [70]:
def seq_fibonacci_2(n):
    s = [0] if n==0 else [0, 1]
    for i in range(2, n + 1):
        f = sum(s[-2:])
        s.append(f)
    return s

print(seq_fibonacci_2(10))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
In [71]:
def seq_fibonacci_3(n):
    s = [0, 1]
    for i in range(2, n + 1):
        f = sum(s[-2:])
        s.append(f)
    return list(s[:n + 1])

print(seq_fibonacci_3(10))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

A funções zip e enumerate¶

Por vezes queremos fazer operações com os elementos de uma lista, ou tupla, considerando a posição desses elementos na lista ou tupla. Outras vezes queremos fazer operações considerando duas listas e combinando seus respectivos elementos. Nos dois caso, as funções enumerate e zip. Primeiramente, vejamos o que elas fazem

In [51]:
enomes = enumerate(nomes)
type(enomes)
print(enomes)
for dpl in enomes: print(dpl)
<enumerate object at 0x7fbad0066bc0>
(0, 'Mariana')
(1, 'João')
(2, 'Pedro')
(3, 'Júlia')
(4, 'Renata')
(5, 'Diego')
(6, 'Sofia')
(7, 'Ricardo')
In [52]:
z_nms_p1_p2 = zip(nomes, prova_1, prova_2)
print(type(z_nms_p1_p2))
print(z_nms_p1_p2)
for z in z_nms_p1_p2: print(z)
<class 'zip'>
<zip object at 0x7fbad2125f80>
('Mariana', 4, 10)
('João', 4.6, 8.0)
('Pedro', 5.2, 9.3)
('Júlia', 3.9, 1)
('Renata', 6.3, 7)
('Diego', 2.2, 5.2)
('Sofia', 5.2, 1)
('Ricardo', 5.0, 6.9)

Exemplo: cálculo do valor presente líquido de um fluxo de caixa¶

Calcule o VPL do seguinte fluxo de caixa, considerando as seguintes taxas de desconto: 5%, 7% e 10%

tempo Fluxo de caixa
0 -2000
1 -500
2 200
3 700
4 1200
5 1500
In [53]:
fluxo = [-2000, -500, 200, 700, 1200, 1500]


def vpl(r, fc):
    v = 0
    for t, f in enumerate(fc):
        v += f / (1 + r) ** t
    return v
        
rs = [0.05, 0.07, 0.1]
for taxa in rs: print(vpl(taxa, fluxo))
472.43395792611364
263.76006353460275
-12.337706689186007

Exemplo: cálculo das médias ponderadas¶

Contrua uma função capaz de calcular a média ponderada dos correspondentes números em duas listas. Aplique essa função para calcular as médias das notas na tabela dando pesos 1 e 2 para a primeira e segunda provas, respectivamente, e dado pesos 2 e 3, para a primeira e paraa segunda prova, respectivamente.

Nome Prova_1 Prova_2
Mariana 4 10
João 4.6 8.0
Pedro 5.2 9.3
Julia 3.9 1
Renata 6.3 7
Diego 2.2 5.2
Sofia 5.2 1
Ricardo 5.0 6.9
In [54]:
nomes = ["Mariana", "João", "Pedro", "Julia", "Renata", "Diego", "Sofia", "Ricardo"]
prova_1 = [4, 4.6, 5.2, 3.9, 6.3, 2.2, 5.2, 5.0]
prova_2 = [10, 8.0, 9.3, 1, 7, 5.2, 1, 6.9]


def media_ponderada(l1, l2, w1, w2):
    s1, s2 = w1 / (w1 + w2), w2 / (w1 + w2)
    medias = [round(s1 * n1 + s2 * n2, 1) for n1, n2 in zip(l1, l2)]
    return(medias)

pesos = [(1, 2), (2, 3)]
for w1, w2 in pesos: print(media_ponderada(prova_1, prova_2, w1, w2)) 
        
[8.0, 6.9, 7.9, 2.0, 6.8, 4.2, 2.4, 6.3]
[7.6, 6.6, 7.7, 2.2, 6.7, 4.0, 2.7, 6.1]

Alguns métodos do objeto list¶

Métodos são funções que pertencem ao objeto, usualmente porque usam dados desse objeto ou altera esses dados. Para evocar um método, digitamos o nome do objeto seguido de um ponto e o nome do método seguido de parênteses vazios ou contendo argumentos para o método.

Método Descrição
append() adiciona um elemento ao final da lista
clear() remove todos os elementos da lista
copy() retorna uma cópia da lista
count() retorna o número de elementos com o valor especificado
extend() acrescenta os elementos da lista informada ao final da lista
index() retorna o índice do primeiro elemento com o valor informado
insert() acrescenta um elemento na posição especificada
pop() retorna e remove o elemento na posição especificada
remove() remove o primeiro elemento com o valor especificado
reverse() inverte a ordem da lista

^| sort() | ordena a lista |

In [55]:
print(nomes)
nomes.append("Godofredo")
print(nomes)
['Mariana', 'João', 'Pedro', 'Julia', 'Renata', 'Diego', 'Sofia', 'Ricardo']
['Mariana', 'João', 'Pedro', 'Julia', 'Renata', 'Diego', 'Sofia', 'Ricardo', 'Godofredo']
In [56]:
lista = [2, 5, 2, False]
print(lista)
lista.clear()
print(lista)
[2, 5, 2, False]
[]
In [57]:
lista = [3, 5, 3, False]
alias_de_lista = lista
copia_de_lista = lista.copy()
print(lista)
print(alias_de_lista)
print(copia_de_lista)
alias_de_lista.clear()
print(lista)
print(alias_de_lista)
print(copia_de_lista)
[3, 5, 3, False]
[3, 5, 3, False]
[3, 5, 3, False]
[]
[]
[3, 5, 3, False]
In [58]:
print(copia_de_lista.count(2))
print(copia_de_lista.count(5))
0
1
In [59]:
lista = [2, 1]
lista.extend(copia_de_lista)
print(lista)
[2, 1, 3, 5, 3, False]
In [60]:
nomes.index("Godofredo")
Out[60]:
8
In [61]:
nomes.insert(2, "Matilde")
print(nomes)
['Mariana', 'João', 'Matilde', 'Pedro', 'Julia', 'Renata', 'Diego', 'Sofia', 'Ricardo', 'Godofredo']
In [62]:
nome_removido = nomes.pop() # caso usado sem argumento, o método pop remove o último elemento da lista
print(nome_removido)
print(nomes)
Godofredo
['Mariana', 'João', 'Matilde', 'Pedro', 'Julia', 'Renata', 'Diego', 'Sofia', 'Ricardo']
In [63]:
print(lista)
lista.pop(1)
print(lista)
[2, 1, 3, 5, 3, False]
[2, 3, 5, 3, False]
In [64]:
print(nomes)
nomes.remove("Matilde")
print(nomes)
['Mariana', 'João', 'Matilde', 'Pedro', 'Julia', 'Renata', 'Diego', 'Sofia', 'Ricardo']
['Mariana', 'João', 'Pedro', 'Julia', 'Renata', 'Diego', 'Sofia', 'Ricardo']
In [65]:
print(lista)
lista.reverse()
print(lista)
[2, 3, 5, 3, False]
[False, 3, 5, 3, 2]
In [66]:
lista.sort()
print(lista)
[False, 2, 3, 3, 5]

Operações com lista¶

lista_1 + lista_2 resulta na conexão das duas listas

lista * 3 resulta em uma lista conectada com ela mesma 3 vezes

In [67]:
lista_3 = [1, 2, 3]
lista_4 = [4, 5, 6]
lista_5 = [7, 8, 9]
lista_6 = lista_1 + lista_2 + lista_3
print(lista_6)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/tmp/ipykernel_2229/2840605456.py in <module>
      2 lista_4 = [4, 5, 6]
      3 lista_5 = [7, 8, 9]
----> 4 lista_6 = lista_1 + lista_2 + lista_3
      5 print(lista_6)

NameError: name 'lista_1' is not defined
In [ ]:
lista_7 = lista_3 * 3
print(lista_5)

A instrução for [variável] in:¶

In [ ]:
somas = [] # cria uma lista vazia
print(lista_2)
for sublista in lista_2: # o código identado abaixo será executado para todos os elementos de lista_2
    soma = sum(sublista) # calcula a soma dos itens do elemento da lista lista_2
    somas.append(soma)   # acrescenta à lista somas o valor dessa soma
    
print(somas)
In [ ]:
print(lista_2)
somas = [sum(lista) for lista in lista_2]
print(somas)

Você pode inserir um loop for dentro de outro loop for. Por, exemplo, o código abaixo cria uma tabela de tabuada:

In [ ]:
numeros = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
tabuada = []


for i in numeros:
    produtos = []
    for j in numeros:
        produtos.append(i * j)
    
    tabuada.append(produtos)
    
print(tabuada)       # lista com a tabuada dos números de zero a 9
print()              # linha vazia
print(tabuada[7])    # tabuada do sete
print()              # linha vazia
print(tabuada[7][6]) # sete vezes seis

Usando list comprehension, podemos gerar a tabuada com um código mais sintético:

In [ ]:
[ [n * m for m in numeros] for n in numeros]

Exemplo: imagine que a lista prova_1 corresponda a notas obtidas pelos alunos descritos na lista nomes. Para obter uma lista dos alunos que obtiveram nota abaixo de 5, podemos executar o código abaixo:

In [ ]:
alunos_com_nota_baixa = []

for nota  in prova_1:
    if nota < 5:
        i = prova_1.index(nota)
        alunos_com_nota_baixa.append(nomes[i])
        
print(alunos_com_nota_baixa)

Também nesse caso, podemos usar list comprehension para gerar o mesmo resultado com um código mais sintético. Com há uma seleção dos elementos da lista original que serão usados para gerar os elementos da lista final, a condição para que o elemento da lista original seja selecionado deve ser informada como se segue:

[expressão(variável) for variável in lista if condição(variável)]

No nosso exemplo:

In [ ]:
[nomes[prova_1.index(nota)] for nota in prova_1 if nota < 5]

Tipo str¶

Um objeto do tipo str é um objeto que contém texto. Ele é criado, digitando-se o texto entre aspas simples ou duplas, como em, por exemplo:

In [ ]:
texto_1 = "Isso é um objeto str"
print(texto_1)

Escape caracters¶

São caracteres especiais inseridos combinando a barra invertida () com outro caracter.

Para inserir aspas duplas no texto, delimite-o com aspas simples ou use \".

Para inserir aspas simples no texto, delimite-o com aspas duplas ou use \".

Para inserir uma nova linha, use \n.

Para inserir uma tabulação, use \t.

Para inserir o character de uma barra invertida, use \

In [ ]:
texto_2 = "Uma linha. \n Uma nova linha. \n \"entre aspas\" \n\ttabulação \n barra invertida: \\"
print(texto_2)

Caso queira desativar a barra invertida como indicador de escape character, prenote o texto com a letra r (de raw, bruto):

In [ ]:
texto_3 = r"Uma linha. \n Uma nova linha. \n \"entre aspas\" \n barra invertida: \\"
print(texto_3)

Objetos str e objetos list¶

Os dados do tipo str se comportam muitas vezes como se fossem um list de caracters. Como tal, eles podem ser fatiados:

In [ ]:
print(texto_1[-1])
In [ ]:
print(texto_1[10:])

Eles também podem ser conectados usando o operador +:

In [ ]:
nome = 'Clara'
sobrenome = 'Barbosa'
nome_completo = nome + ' ' + 'Barbosa'
print(nome_completo)

Métodos do objeto str¶

Para encontrar a posição em que um padrão de texto aparece em outro texto, use o método find:

In [ ]:
nome_completo.find('Bar')

O método find diferencia maiúsculas de minúsculas e retorna -1 caso não encontre o padrão procurado.

In [ ]:
nome_completo.find('bar')

Para fazer usar o método find sem diferenciar maiúsculas de minúsculas use o método lower, ou, ainda melhor casefold, para transformar todas as letras em minúsculas:

Tanto o método lower quanto o método casefold convertem maiúsculas em minúsculas, porém, o método casefold é mais agressivo que o método lower. Por exemplo, o casefold converte ß em ss. Para palavras da língua portuguesa, os dois métodos são equivalentes.

In [ ]:
texto_principal = nome_completo.casefold()
texto_procurado = 'bAR'.casefold()
texto_principal.find(texto_procurado)

Caso queira converter todas as letras de um texto em maiúscula, use o método upper:

In [ ]:
nome_completo.upper()

Para concatenar diversos objetos str separando-os com um outro objeto str, use o método join:

In [ ]:
print("; ".join(nomes))
In [ ]:
print("\n".join(nomes))

Conversão de tuplas em listas e vice-versa¶

Para converter uma lista em tupla, use a função tuple com a lista como argumento.

Para converter uma tupla em uma lista, use a função list com a tuplas como argumento.

In [ ]:
print(type(lista))
tupla_da_lista = tuple(lista)
print(type(tupla_da_lista))

print(type(tupla_1))
lista_da_tupla = list(tupla_1)
print(type(lista_da_tupla))

Dicionários¶

Dicionários (dict) são coleções de objetos aos quais são associados termos de identificação, chamados chaves (keys). Para criar um dicionário, digitamos, entre chaves ({}) pares do tipo chave:elemento separados por vírgula. Posterioremente, para recuperar um elemento específico de um dicionário, usamos, como índice, a chave correspondente. Por exemplo, imagine que tenhamos as seguintes informação sobre as idades de um grupo de pessoas:

Nome Idade (anos)
Rafaela 23
Pedro 18
Rita 17
Ana Maria 32
Felipe 47

Podemos armazernar essas informações na forma de um dicionário, conforme exemplificado abaixo:

In [ ]:
idades = {'Rafaela':23, 'Pedro':18, 'Rita':17, 'Ana Maria':32, 'Felipe': 47}

Agora, se quisermos recuperar a idade de alguma dessas pessoas, por exemplo, de Ana Maria, digitamos

In [ ]:
idades['Ana Maria']

Os elementos dos dicionários são identificados pela chave à qual são associados e não pela ordem em que aparecem no dicionário. No nosso exemplo, nenhuma das chaves do dicionário é 0, de tal sorte que o código abaixo retorna uma mensagem de erro:´´

Dicionários também podem ser criados usando a função dict. Como argumento, forneça uma lista de tuplas com a forma (chave, objeto), como em, por exemplo:

In [ ]:
pares = [('Rafaela',23), ('Pedro',18), ('Rita',17), ('Ana Maria',32), ('Felipe', 47)]
idades = dict(pares)
print(idades['Ana Maria'])

Exemplo:¶

O professor Epaminondas acaba de corrigir as duas provas realizadas por seus alunos. As notas obtidas são exibidas na tabela abaixo

Nome Prova 1 Prova 2
Mariana 4,0 10,0
João 4,6 8,0
Pedro 5,2 9,3
Julia 3,9 1,0
Renata 6,3 7,0
Diego 2,2 5,2
Sofia 5,2 1,0
Ricardo 5,0 6,9

Observe que os nomes dos alunos já foram armazenados na lista nomes e que as notas nas duas provas também já estão armazenadas nas listas prova_1 e prova_2. Todavia podemos organizar os dados em um dicionário, para o qual cada elemento é uma coluna:

In [ ]:
print(nomes)
print(prova_1)
print(prova_2)
notas = {"Nome":nomes, "Prova 1":prova_1, "Prova 2":prova_2}
print(notas)

Para obter a nota de Júlia na prova 1, por exemplo, podemos usar a expressão

In [ ]:
notas['Prova 1'][notas['Nome'].index('Júlia')]

Você pode adicionar um novo valor a un dicionário. Por exemplo, se quizermos adicionar uma coluna contendo o ano de ingresso no dicionário notas, podemos escrever o código abaixo:

In [ ]:
notas['Ingresso'] = [2019, 2020, 2018, 2019, 2017, 2020, 2020, 2019]
notas

Métodos dos objetos dictionary¶

Nome Descrição
clear() Remove todos os itens do dicionário
copy() Cria uma cópia do dicionário
fromkeys Cria um subdicionário com as chaves informadas
get Retorna o valor associado a uma dada chave
items Retorna uma lista de duplas (chave, valor)
keys Retorna uma visualização das chaves do dicionário
pop Retorna e remove o elemento com a chave informada
popitem Retorna o par (chave, elemento) com a chave informada
setdefault Retornao valor de uma chave, se existir, senão,
insere a chave com o valor no dicionário
update atualiza o dicionário com os elementos
de outro dicionário
values retorna uma lista com os valores do dicionário
In [ ]:
x = idades.pop('Rafaela')
print(x)
print(idades)
In [ ]:
idades.setdefault('Rafaela', 23)
print(idades)
In [ ]:
x = idades.popitem()
print(x)
idades.setdefault(x[0], x[1])
print(idades)
In [ ]:
idades.update({'Ana Maria': 31})
print(idades)
In [ ]:
print(idades.values())

Conjuntos¶

Conjuntos são coleções de objetos não repetidos e não indexados. Para criar um conjunto, listamos todos seus elementos, separados por vírgula e entre chaves. Elementos repetidos são desconsiderados.

In [ ]:
conjunto_1 = {1, 1, 2, 3, 4, 5, 2, 3}
print(conjunto_1)
conjunto_2 = {4, 5, 6, 7, 4}
print(conjunto_2)

Operações com conjuntos¶

In [ ]:
# União:
conjunto_1 | conjunto_2
In [ ]:
# União usando o método union
conjunto_1.union(conjunto_2)
In [ ]:
# Intersecção
intersec = conjunto_1 & conjunto_2
print(intersec)
In [ ]:
# Intersecção usando o método intersection
conjunto_1.intersection(conjunto_2)
In [ ]:
# Diferença
diferenca = conjunto_1 - conjunto_2
print(diferenca)
In [ ]:
# Diferença usando o método difference
conjunto_1.difference(conjunto_2)
In [ ]:
# Diferença simética: elementos em apenas um dos dois conjuntos:
difsim = conjunto_1 ^ conjunto_2
print(difsim)
In [ ]:
# Diferença simétrica usando o método symetric_difference:
conjunto_1.symmetric_difference(conjunto_2)
In [ ]:
# inclusão de um elemento
conjunto_2.add(13)
print(conjunto_2)
In [ ]:
# teste se um conjunto é subconjunto de outro

print(intersec <= conjunto_1) # intersec é subconjunto de conjunto 1?
print(difsim <= conjunto_1) # difsim é subconjunto de conjunto 1?
print(conjunto_1 <= conjunto_1) # difsim é subconjunto de conjunto 1?
print(difsim < conjunto_2) # difsim é subconjunto próprio de conjunto 2?
print(conjunto_2 < conjunto_2) # difsim é subconjunto próprio de conjunto 2?
print(conjunto_1 > difsim) # difsim é subconjunto próprio de conjunto 1?
print(conjunto_1 < conjunto_1) # difsim é subconjunto próprio de conjunto 1?
print(conjunto_2 >= intersec) # intersec é subconjunto de conjunto 2?

Conversão entre dict list e tuple¶

Use as funções set dict e tuple para converter entre os tipos.

In [ ]:
print(list(conjunto_1))
print(tuple(conjunto_2))
print(set(lista_1))
print(set(tupla_1))

Exemplo.¶

Quais são os anos de ingresso ´que aparecem na elemento "idade" do dicionário provas?

In [ ]:
print(set(notas['Ingresso']))
In [ ]:
# Para converter os valores de um dicionário em uma lista,uma tupla, ou
# um conjunto, use o método values:
print(list(idades.values()))

# Para converter as chaves de um dicionário em uma lista, uma tupla, ou
# um conjunto, use o método keys:
print(tuple(idades.keys()))

# Para converter um dicionário em uma lista, uma tupla ou um conjunto
# de pares (chave, valor), use o método items
print(set(idades.items()))
In [ ]:
for a in enumerate(tupla_1): 
    print(a)