MAC0216 - Técnicas de Programação I

Aula 22 - Introdução à Python

Nosso primeiro programa em Python

In [1]:
print("Olá, mundo!")
Olá, mundo!

Valores e tipos

Um valor é um dos elementos básicos que um programa manipula. Um valor tem sempre um tipo.

Por exemplo, 15 é do tipo inteiro, enquanto "Olá, mundo!" é do tipo texto (= cadeia de caracteres = string). Em Python, esses dois tipos são chamados de int e str, respectivamente. O valor 3.75 é do tipo real, chamado em Python de float.

Para consultar o tipo de um valor, você pode usar o comando type, como no exemplo abaixo.

In [2]:
print(type(15))
<class 'int'>
In [3]:
print(type('Olá, mundo!'))
<class 'str'>
In [4]:
print(type(3.75))
<class 'float'>

Atenção: um valor como "3.75" parece do tipo real, mas na verdade é uma cadeia de caracteres (observe as aspas!).

In [5]:
print(type("3.75"))
<class 'str'>

Variáveis

Uma variável é um nome que referencia um valor. Para criar uma nova variável e associar um valor a ela, usamos um comando de atribuição.

Veja a seguir exemplos de comandos de atribuição em Python; esses comandos criam variáveis chamadas a, b e c.

In [6]:
a = 10
b = c =  5 + a / 4

A segunda linha do bloco acima se trata de um comando de atribuição múltipla. Em uma atribuição desse tipo, uma sequência de variáveis recebe um mesmo valor (o resultado da expressão que aparece do lado direito do operador de atribuição = mais à direita no comando).

Para escrever o valor de uma variável na saída, você pode usar a função print().

In [7]:
print(a, type(a))
print(b, type(b))
10 <class 'int'>
7.5 <class 'float'>

Podemos passar quantos valores quisermos para a função print() escrever. Os valores devem ser separados por vírgulas.

Os programadores devem escolher os nomes das variáveis de maneira cuidadosa, de modo que eles possam facilitar a compreensão do programa. Uma boa dica é usar nomes que indiquem a função das variáveis dentro do programa.

Um nome de variável pode conter tanto letras quanto números, mas ele deve sempre começar com uma letra. As letras podem ser maiúsculas ou minúsculas. O caracter underscore _ também pode aparecer no nome; geralmente ele é usado em nomes compostos por mais de uma palavra (ex.: velocidade_carro e nome_rua).

Expressões matemáticas e lógicas

Operadores de comparação

Python possui os operadores de comparação tradicionais das linguagens de programação: ==, !=, >, >=, < e <=.

In [8]:
12 <= 15 
Out[8]:
True
In [9]:
12 == 13
Out[9]:
False

O resultado de uma operação de comparação é sempre um valor do tipo bool:

In [10]:
resultado = 12 == 12
print(resultado, type(resultado))
True <class 'bool'>

True e False são valores especiais, os únicos possíveis no tipo bool:

In [11]:
print(type(True))
print(type(False))
<class 'bool'>
<class 'bool'>

Operadores lógicos

Python não restringe o uso dos operadores lógicos and, or e not apenas a operandos do tipo bool. Veja abaixo como cada um desses operadores funcionam:

  • Na expressão x and y, primeiro o x é avaliado. Se o x é falso, então o seu valor é devolvido como resultado da operação de and. No caso contrário, y é avaliado e o valor resultante será o resultado da operação and.

  • Na expressão x or y, primeiro o x é avaliado. Se o x é verdadeiro, então o seu valor é devolvido como resultado da operação de and. No caso contrário, y é avaliado e o valor resultante será o resultado da operação and.

  • Na expressão not x, se o x é falso, então o valor verdadeiro é devolvido como resultado da operação not. No caso contrário, a operação devolve falso.

Além disso, em uma expressão lógica, os valores 0 (int), 0.0 (float) e "" (str) são considerados equivalentes ao valor booleano False. Qualquer coisa diferente deles é considerado equivalente a True.

Veja os exemplos a seguir:

In [12]:
x = 5
x > 0 and x < 10
Out[12]:
True
In [13]:
0.0 and x == 5
Out[13]:
0.0
In [14]:
17 and x == 5
Out[14]:
True
In [15]:
x == 5 and 17
Out[15]:
17
In [16]:
17 or x == 6
Out[16]:
17
In [17]:
not(17) or x == 6
Out[17]:
False
In [18]:
not(17) or 18
Out[18]:
18

Os operadores lógicos têm menor precedência que os operadores matemáticos. Assim, em uma expressão, primeiro são avaliados os operadores matemáticos, depois são avaliados os operadores lógicos. O ordem de precedência (da maior para a menor) para os operadores lógicas é a seguinte:

  1. not
  2. and
  3. or

Comparações podem ser feitas de forma encadeada. Por exemplo, x < y <= z é equivalente a x < y and y <= z.

Problema

Dados um número inteiro n > 0 e as médias de n alunos, determinar quantos ficaram de recuperação. Um aluno está de recuperação se sua média estiver entre 3,0 e 5,0 (nota máxima é 10,0).

Solução

In [19]:
n = int(input("Digite n: "))
rec = 0
cont = 0
while cont < n:
    media = float(input("Digite uma nota: "))
    if 3.0 <= media < 5.0: #  essa condição equivale a: 3.0 <= media < 5.0:
        rec = rec + 1
    cont = cont + 1
print(rec, "alunos ficaram de recuperação")
Digite n: 3
Digite uma nota: 5.6
Digite uma nota: 3.2
Digite uma nota: 4.5
2 alunos ficaram de recuperação

Tipos numéricos (int, float, complex) e suas operações

  • o tipo de dados associado a valores que são números inteiros é o int. Valores numéricos do tipo int têm precisão ilimitada.
  • O tipo de dados em Python associado a números reais é o float (que vem de floating-point). O tipo float geralmente é implementado usando o tipo double de C.
  • Um número complexo z do tipo complex possui uma parte real (z.real) e uma parte imaginária (z.imag), ambas são valores em ponto flutuante.

Podemos expressar um valor do tipo float usando diferentes notações:

In [22]:
a = 0.0003
print("a =", a, ", tipo de a:", type(a))
b = 3e-4
print("b =", b, ", tipo de b:", type(b))
a = 0.0003 , tipo de a: <class 'float'>
b = 0.0003 , tipo de b: <class 'float'>

Do mesmo modo que podemos transformar um valor do tipo string para um valor do tipo inteiro usando a função int, também podemos transformar um valor do tipo string para um valor do tipo real usando a função float.

In [23]:
num1 = float("3.75231")
print("%.2f" %(num1))    # '%.2f' se refere a um número real com duas casas depois da vírgula
print(type(num1))

num2 = (float("2"))
print(num2, type(num2))
3.75
<class 'float'>
2.0 <class 'float'>

Python tem todos os operadores matemáticos tradicionais para tipos numéricos: +, -, *, /, //, %.

O resultado da operação de divisão / é sempre um número do tipo float (mesmo quando o quociente não tem casas decimais). Veja os exemplos a seguir:

In [24]:
a = 3 / 4
print(a, type(a))

b = 4 / 2
print(b, type(b))

c = 2.56 / 2
print(c, type(c))

d = 2.56 / 4.35
print(d, type(d))
0.75 <class 'float'>
2.0 <class 'float'>
1.28 <class 'float'>
0.5885057471264369 <class 'float'>

O operador // realiza a divisão inteira de dois números, enquanto o operador % devolve o resto da divisão inteira entre dois números. Veja um exemplo de uso a seguir:

In [1]:
minutos = 252
horas = minutos // 60
minutos_excedentes = minutos % 60
print(minutos, "minutos =", horas, "horas e", minutos_excedentes, "minutos")
252 minutos = 4 horas e 12 minutos

Outras operações disponíveis em Python para tipos numéricos são:

  • abs(x) -- valor absoluto ou magnitude de x
  • int(x) -- x convertido para int
  • float(x) -- x convertido para float
  • complex(re, im) -- cria um objeto do tipo complex com parte real re e parte imaginária im
  • conjugate() -- conjugado do número complexo c
  • divmod(x, y) -- o par (x // y, x % y)
  • pow(x, y) ou x ** y -- x elevado a y

Para números do tipo int e float, as seguintes operações também estão disponíveis:

  • math.trunc(x)-- devolve o valor de x sem casas decimais
  • round(x[, n]) -- arredonda x para n dígitos decimais (n = 0 é o padrão)
  • math.floor(x)-- devolve o chão de x (o maior inteiro <= x)
  • math.ceil(x)-- devolve o teto de x (o menor inteiro >= x)

Nos módulos math e cmath, há várias outras operações numéricas:

https://docs.python.org/3/library/math.html

https://docs.python.org/3/library/cmath.html

Regras de precedência dos operadores matemáticos

Agora que já vimos os operadores matemáticos, é pertinente falar sobre as regras de precedência que regem a ordem de avaliação das operações dentro de uma expressão matemática. Python segue a mesma convenção usada na matemática; a ordem de avaliação dos operadores, do de maior precedência para o de menor precedência, é a seguinte:

  • Parênteses ( )
  • Exponenciação **
  • Multiplicação *, divisão /, divisão inteira // e resto da divisão inteira %, que possuem a mesma precedência
  • Adição + e subtração -, que possuem a mesma precedência

Usamos parênteses para forçar que uma expressão seja avaliada em uma determinada ordem desejada. Ex.: 2 * (3-1) = 4, mas 2 * 3 - 1 = 5.

Operadores com a mesma precedência são avaliados da esquerda para a direita. Ex: 10 / 2 * 2 = 10 e 10 / (2 * 2) = 2.5. Mas há uma exceção para essa regra: a exponenciação. Ex: 2**3**2 equivale a 2**(3**2) que é 512; note que isso é diferente de (2**3)**2, que é 64.

Entrada de dados com input e laço while

A função input() lê dados digitados pelo usuário no teclado e devolve-os ao programa. A função recebe como parâmetro de entrada (valor passado entre parênteses) a mensagem que será mostrada na tela, para avisar ao usuário que ele precisa digitar alguma coisa. O valor lido do teclado e devolvido pela input() ao programa é sempre do tipo string.

Para transformar um valor do tipo string para um valor do tipo inteiro, usamos a função int().

Esse programa exemplifica o uso de um outro tipo de comando, o comando while. O comando while nos permite executar um bloco de comandos repetidas vezes.

Podemos descrever o fluxo de execução do while por meio dos seguintes passos:

  1. Avalia a condição (expressão lógica) do while, o que resulta em um valor que pode ser True (verdadeiro) ou False (falso).
  2. Se a condição for falsa, sai do bloco do while e continua a execução a partir do comando seguinte.
  3. Se a condição for verdadeira, executa o corpo (bloco de comandos) do while e depois volta ao passo I.

Esse tipo de fluxo é chamado de laço (porque o terceiro passo permite uma volta ao passo inicial).

Problema

Dados números inteiros n e k, com k>=0, determinar nk. Por exemplo, dados os números 3 e 4 o seu programa deve escrever o número 81.

Obs.: Esse exercício corresponde ao exercício 4 da lista de exercícios sobre inteiros.

Solução

In [20]:
n = int(input("Digite o valor de n: "))        
k = int(input("Digite o valor de k: "))       
pot = 1
i = 0
while i < k:
    pot = pot*n
    i = i + 1
print("O valor de", n, "elevado a", k, "é", pot)
Digite o valor de n: 3
Digite o valor de k: 4
O valor de 3 elevado a 4 é 81

Observação: Python possui um operador para o cálculo da exponenciação, o ** (ver exemplo abaixo).

In [21]:
n = int(input("Digite o valor de n: "))        
k = int(input("Digite o valor de k: "))        
print("O valor de", n, "elevado a", k, "é", n**k) 
Digite o valor de n: 3
Digite o valor de k: 4
O valor de 3 elevado a 4 é 81

Comandos para a execução condicional: if -elif - else

Comandos para a execução condicional dão ao programador a habilidade de verificar condições e mudar o comportamento do programa de acordo com isso.

O comando if é a forma mais simples de se fazer uma execução condicional. A expressão lógica depois do if é chamada de condição. Se ela for verdadeira, o bloco de comandos indentados será executado. Se ela for falsa, nenhum comando de dentro do bloco indentado será executado.

Não há um limite para a quantidade de comandos que podem aparecer dentro de um bloco do if, mas sempre deve haver pelo menos um comando no bloco.

Uma segunda forma do comando if é a execução alternativa, ou comando if-else, em que há duas possibilidades de execução e é a condição quem determina qual delas será realizada. Os comandos relacionados a uma das possibilidades aparecem como um bloco indentado do if e serão executados quando a condição for verdadeira. Os comandos da outra possibilidade aparecem como um bloco indentado do else e serão executados quando a condição do if for falsa. Veja um exemplo de uso a seguir:

In [26]:
x = int(input("Digite um número: "))
if x > 0:
    print(x, "é um número positivo.")
else:
    print(x, "NÃO é um número positivo.")

print("Tchau!")
Digite um número: -3
-3 NÃO é um número positivo.
Tchau!

Podemos usar comandos if ou if-else de forma aninhada, como mostrado no exemplo a seguir.

In [27]:
x = int(input("Digite um numero: "))
y = int(input("Digite um numero: "))
if x < y:
    print(x, "é menor que", y)
else:
    if x > y:
        print(x, "é maior que", y)
    else:
        print(x, "é igual a", y)
Digite um numero: 10
Digite um numero: 5
10 é maior que 5

Podemos substituir o uso de um if ou if-else aninhado em um else pelo elif, como mostrado a seguir:

In [28]:
x = int(input("Digite um numero: "))
y = int(input("Digite um numero: "))
if x < y:
    print(x, "é menor que", y)
elif x > y:
    print(x, "é maior que", y)
else:
    print(x, "é igual a", y)
Digite um numero: 10
Digite um numero: 5
10 é maior que 5

Podemos ter mais de um elif associado a um if. Além disso, também podemos ter if-elif sem um else.

Problema

Dados um número inteiro n, n>0, e uma sequência com n médias de MAC0216, determinar:

1. quantos alunos aprovados (média ≥ 5.0);
2. item 1. + quantos alunos em recuperação (3.0 ≤ média ≤ 5.0);
3. item 2. + quantos alunos reprovados (média < 3.0); e
4. item 3. + quantos alunos excelentes (média ≥ 8.0). 

Por exemplo, para a sequência

6

2.3 3.0 5.0 6.5 8.7 4.9

Temos:

3 alunos aprovados

2 alunos em recuperação

1 alunos reprovados

1 alunos excelentes

Solução

In [29]:
n = int(input("Digite o número de alunos: "))
conta_aprovados  = 0
conta_excelentes = 0
conta_recuperacao = 0
conta_reprovados  = 0

while n > 0:
    media = float(input("Digite uma média: "))
    n = n - 1
    if media >= 5.0:
        conta_aprovados = conta_aprovados + 1
        if media >= 8.0:
            conta_excelentes = conta_excelentes + 1
    elif media >= 3.0:
        conta_recuperacao = conta_recuperacao + 1
    else:
        conta_reprovados = conta_reprovados + 1

print("Total de alunos aprovados: ", conta_aprovados)
print("Total de alunos excelentes: ", conta_excelentes)
print("Total de alunos de recuperacao: ", conta_recuperacao)
print("Total de alunos reprovados: ", conta_reprovados)
Digite o número de alunos: 6
Digite uma média: 2.3
Digite uma média: 3
Digite uma média: 5
Digite uma média: 6.5
Digite uma média: 8.7
Digite uma média: 4.9
Total de alunos aprovados:  3
Total de alunos excelentes:  1
Total de alunos de recuperacao:  2
Total de alunos reprovados:  1

Criação de laços com o comando for e a função range

Quando se sabe exatamente quantas vezes é preciso repetir a execução de um bloco, uma alternativa ao uso do while é o uso do comando for combinado à função range. Veja um exemplo de programa que usa o for a seguir:

In [ ]:
print("Iniciando contagem:")
for i in range(5):
    print(i)
print("Bum!")

Usando while, o programa acima ficaria duas linhas mais longo:

In [ ]:
print("Iniciando contagem:")
i = 0
while i < 5 :
    print(i)
    i = i + 1
print("Bum!")

A função range() devolve um objeto iterável (ou seja, que pode ser iterado). Quando usado em um laço for, ele provê, a cada ciclo do laço, o próximo valor na sequência de números inteiros no intervalo.

A função range tem 3 parâmetros, que definem a sequência de números a ser criada.

range( [início], fim[, passo] )

  • início - valor onde o intervalo deve começar
  • fim - valor (menos um) onde o intervalo deve finalizar
  • passo - passo (intervalo entre os elementos da sequência)

o intervalo de números cobertos pela função range é fechado no início e aberto no fim.

Quando o passo desejado é 1 (um), o valor não precisa ser passado a função range. E quando o início desejado é 0 (zero) e o passo 1 (um), pode-se passar apenas o fim (como fizemos no exemplo acima).

O passo pode ser um número negativo. Veja o exemplo abaixo:

In [31]:
for i in range(100, 50, -10):
    print(i)
100
90
80
70
60

Problema

Dados um número inteiro n, n > 0, e uma sequência com n números inteiros, determinar quantos números da sequência são pares e quantos são ímpares. Por exemplo, para a sequência

6 -2 7 0 -5 8 4

o seu programa deve escrever o número 4 para o número de pares e 2 para o de ímpares.

Solução

In [32]:
n = int(input("Digite o tamanho da sequência: "))
conta_par = 0
conta_impar = 0
for i in range(n): 
    num = int(input("Digite um número da sequência: "))
    if num % 2 == 0:
        conta_par = conta_par + 1
    else:
        conta_impar = conta_impar + 1
print(conta_par, "números pares")
print(conta_impar, "números ímpares")
Digite o tamanho da sequência: 4
Digite um número da sequência: 6
Digite um número da sequência: 7
Digite um número da sequência: 1
Digite um número da sequência: 9
1 números pares
3 números ímpares

Comentários de linha e comentários em bloco

O caracter # marca o início de um comentário de linha em Python, ou seja, tudo que está entre o caractere # e o final da linha será ignorado pelo interpretador. Veja o exemplo a seguir; nele, o segundo comando de atribuição de valor à variável a é ignorado por estar depois do caracter #.

In [33]:
a = 1
print(a)
#a = a + 1
print(a)   # será que o valor de a foi modificado desde o print anterior?
1
1

Quando o primeiro # de uma linha aparece dentro de uma string, então ele não é entendido como o início de um comentário de linha:

In [34]:
print("Um caracter # dentro de uma string não inicia um comentário!")
Um caracter # dentro de uma string não inicia um comentário!

Para criar comentários que abrangem mais de uma linha, é mais conveniente usarmos a sequência de caracteres ''' para delimitar o início e o fim do bloco de comentário. Veja o exemplo abaixo:

In [35]:
a = 1
'''  Este o início de um comentário em bloco
a = a + 1
A linha acima não modificará o valor da variável a,
por que ela está dentro do bloco de comentário! '''
print(a)
1

Definição de funções

Declaração de função em Python:

def nome_da_função ( parâmetros ):
    '''
    docstring contendo comentários sobre a função.
    Embora opcionais, são fortemente recomendados. Os comentários
    devem descrever o papel dos parâmetros e o que a função faz.
    '''
    # corpo da função
    |
    | bloco de comandos
    |

Problema

Escreva um programa que leia dois inteiros m e n e calcula o coeficiente binomial

m!/(n!(m-n)!)

ou seja, um programa que calcule quantas formas distintas é possível escolher n elementos de um grupo de m elementos.

Solução usando funções

In [36]:
def main():
    '''
    Programa que calcula binomial
    '''

    print("Calculo de binomial(m, n)")
    m = int(input("Digite o valor de m:"))
    n = int(input("Digite o valor de n:"))

    print ("binomial(%d, %d) = %d" %(m, n, binomial(m,n)))
    
    
#-----------------------------------------------------
def binomial(m,n):
    '''(int,int) -> int

    Recebe dois inteiros m e n e devolve o valor da
    combinação de m n-a-n.

    Utiliza a função fatorial().

    Pré-condição: supõe que m e n são números inteiros não negativos.
    '''

    return fatorial(m)/(fatorial(m-n)*fatorial(n))

#-----------------------------------------------------
def fatorial(k):
    '''(int) -> int

    Recebe um inteiro k e devolve o valor de k!

    Pré-condição: supõe que k é um número inteiro não negativo.
    '''

    k_fat = 1
    i = 2
    while i <= k:
        k_fat *= i
        i += 1

    return k_fat


# início da execução do programa
main()
Calculo de binomial(m, n)
Digite o valor de m:5
Digite o valor de n:2
binomial(5, 2) = 10

Observação: O módulo math do Python possui a função factorial, que calcula o fatorial de um número. Para usar uma função do módulo math, devemos primeiramente importar o módulo no código, usando o comando import math, e depois chamar a função. O exemplo abaixo mostra uma chamada à função factorial.

In [37]:
n = int(input("Digite o valor de n: "))      
print("O valor de %d! é = %d" %(n, math.factorial(n)))
Digite o valor de n: 5
O valor de 5! é = 120

Docstrings

Logo no início das funções main, fat e binomial que criamos, é possível ver um comentário de bloco. Esse tipo de comentário no início de uma função é chamado de docstring, e seu objetivo é documentar a função.

Um docstring deve conter a informação que é essencial de se saber para alguém que quer usar a função. Ele deve explicar de forma concisa o quê a função faz, mas sem entrar em detalhes sobre como isso é feito. Ele deve dizer o significado de cada parâmetro de entrada e também o seu tipo esperado (quando necessário). O docstring deve dizer também o que a função devolve como valor de retorno.

Podemos ver o docstring de uma função usando a função help, como no exemplo abaixo:

In [38]:
help(fatorial)
Help on function fatorial in module __main__:

fatorial(k)
    (int) -> int
    
    Recebe um inteiro k e devolve o valor de k!
    
    Pré-condição: supõe que k é um número inteiro não negativo.

Parâmetros posicionais, parâmetros nomeados e parâmetros com valor padrão

Em Python, pode-se indicar valores padrão (default) para parâmetros na definição de funções. Quando se omite o o valor do parâmetro na chamada da função, o valor padrão será usado. Os valores padrão são definidos usando a forma parâmetro=valor.

Os parâmetros com valor padrão devem ser os mais à direita (ou seja, os finais) na lista de parâmetros de uma função.

Nos exemplos de chamadas a funções mostrados nesta aula até agora, nas chamadas a funções, passamos os valores para os parâmetros na mesma ordem em que foram definidos nas funções. Portanto, a posição do valor na chamada determina a que parâmetro ele corresponde.

Mas também é possível nomear os valores na chamada, o que possibilita passar valores para os parâmetros numa ordem diferente da definida na função.

O exemplo abaixo ilustra essas possibilidades:

In [39]:
def exibe(nomealuno, idade = 18, curso ='Bacharelado em Ciência da Computação'):
    """
    Esta função mostra o nome e a idade de uma pessoa.
    Se a idade não for fornecida, o seu valor padrão (30)
    If age is not provided,
    it's default value 30 would
    be displayed.
    """     
    print("%s (%2d anos) é estudante do curso %s" %(nomealuno, idade, curso))

exibe("Paul Mccartney", 25, "Bacharelado em Matemática")    
exibe("John Lennon", 20)
exibe("Ringo Starr")
exibe(curso = "Licenciatura em Física", nomealuno = "George Harrison")
Paul Mccartney (25 anos) é estudante do curso Bacharelado em Matemática
John Lennon (20 anos) é estudante do curso Bacharelado em Ciência da Computação
Ringo Starr (18 anos) é estudante do curso Bacharelado em Ciência da Computação
George Harrison (18 anos) é estudante do curso Licenciatura em Física

Observe que as seguintes chamadas à função exibe são incorretas:

In [40]:
exibe(curso = "Licenciatura em Física")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-40-597dbb070c03> in <module>
----> 1 exibe(curso = "Licenciatura em Física")

TypeError: exibe() missing 1 required positional argument: 'nomealuno'
In [41]:
exibe(25, "Bacharelado em Matemática")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-41-763af78b082b> in <module>
----> 1 exibe(25, "Bacharelado em Matemática")

<ipython-input-39-4279af4a44a1> in exibe(nomealuno, idade, curso)
      7     be displayed.
      8     """     
----> 9     print("%s (%2d anos) é estudante do curso %s" %(nomealuno, idade, curso))
     10 
     11 exibe("Paul Mccartney", 25, "Bacharelado em Matemática")

TypeError: %d format: a number is required, not str

Observações:

  • Na chamada a uma função que possui dois ou mais argumentos padrão, quando omite-se um argumento que não é o mais à direita na lista de argumentos, todos argumentos à direita desse argumento também devem ser omitidos na chamada.
  • No caso de passagem de argumentos nomeados, a ordem dos argumentos na chamada não é importante. Já numa chamada a função que contém ao menos um argumento não nomeado, a ordem dos argumentos na chamada é importante.
  • Os nomes passados na chamada devem ser nomes de parâmetros definidos na função. Na chamada, deve-se passar no máximo um valor para cada nome de parâmetro.

Testes automatizados com pytest

O pytest é um arcabouço de código aberto para a execução de testes automatizados em Python. Ele não faz parte da biblioteca padrão de Python, mas é bastante popular.

https://docs.pytest.org/

O pytest:

  • Considera que os arquivos com nome *_test.py ou test_*.py são arquivos de teste
  • Executa funções e métodos com nome test_*

Exemplo (extraído da documentação do pytest):

In [ ]:
# content of test_sample.py
def func(x):
    return x + 1


def test_answer():
    assert func(3) == 5

Exemplo: função fatorial e seus testes automatizados

In [2]:
# conteúdo do arquivo test_fatorial.py

def fatorial(n):
    if n < 0:
        return 0
    
    i = fat = 1
    while i <= n:
        fat = fat * i
        i += 1
    return fat

def test_fatorial0():
    assert fatorial(0) == 1
    
def test_fatorial1():
    assert fatorial(1) == 1
    
def test_fatorial2():
    assert fatorial(2) == 2

def test_fatorial4():
    assert fatorial(4) == 24

def test_fatorial5():
    assert fatorial(5) == 120

def test_fatorialMenos1():
    assert fatorial(-1) == 0

Referências:

  1. Videoaulas de Introdução à Ciência da Computação com Python, do prof. Fabio Kon: https://www.youtube.com/playlist?list=PLcoJJSvnDgcKpOi_UeneTNTIVOigRQwcn
  2. Notas de aula para cursos de Introdução à Computação em Python do IME-USP: https://panda.ime.usp.br/cc110/static/cc110/index.html
  3. Livro: Como Pensar Como um Cientista da Computação - Aprendendo com Python: Versão Interativa https://panda.ime.usp.br/pensepy/static/pensepy/index.html
  4. Notas de aula da disciplina MAC2166: https://www.ime.usp.br/~mac2166/1s20/index.html
  5. Livro Fluent Python: Clear, Concise, and Effective Programming: https://www.oreilly.com/library/view/fluent-python-2nd/9781492056348/