Passagem de Parâmetros por Linha de Comando em Python com Argparse
Nesse texto você aprenderá o essencial para trabalhar com linhas de comando em suas aplicações Python.
Um hábito péssimo que eu havia desenvolvido é o de passar dados para o meu programa "na mão". Depois de um tempo enorme fazendo isso, decidi tomar vergonha na cara: comecei a invocar programas por linha de comando e passar parâmetros dessa forma.
Assim sendo, o intuito desse texto é tentar mostrar um pouco do que aprendi desse processo, para que você possa passar informação para o seu código quando este for executado em um terminal de comando, seja Windows, Linux ou Mac.
Instalando e adicionando o módulo argparse em seu projeto
A biblioteca argparse configura interfaces de linha de comando bem amigáveis, com direito até a uma mensagem de ajuda e um pequeno tratamento de erros. Veja no print abaixo, por exemplo, o que aparece quando tento rodar um dos meus scripts em Python sem passar os parâmetros (argumentos) devidos.
Erro: Parâmetro obrigatório está faltando (nome do arquivo a ser processado).
É bastante fácil extrair informações sobre o que deve ser passado pro programa funcionar (ou mesmo bastante sobre seu uso em geral). Basta invocar o script passando o argumento (-h), que nada mais é um conjunto de mensagens de ajuda para o uso do software.
D:\github\SilenceTrimmerForVideo> python main.py -hVemos uma representação bem detalhada, com explicações sobre o funcionamento do programa quando passamos o parâmetro de ajuda (-h).
Ao criar um novo código Python, basta incluir as seguintes linhas abaixo e pronto! Argparse configurado, podemos terminar esse tutorial, tchau e obrigado =P
#importei a biblioteca
import argparse
#criei o objeto que fará o parser, responsável por passar os argumentos em linha de comando
parser = argparse.ArgumentParser()
#essa chamada faz com que os parâmetros recebidos pelo programa sejam armazenados no objeto args
args = parser.parse_args()Ok, não é verdade. Vamos botar a mão na massa e explorar o que é possível fazer com esse objeto parser de linha de comando!
Criando nosso Primeiro Argumento
Vamos começar fazendo algo bem simples: imagine um programa que recebe um número por parâmetro e ele me diz se o mesmo é par ou ímpar. Só que faremos isso informando o valor por linha de comando.
Considere o código abaixo:
#importei a biblioteca
import argparse
def getArguments():
#criei o objeto que fará o parser, responsável por passar os argumentos em linha de comando
parser = argparse.ArgumentParser()
#configurei o primeiro parâmetro a ser recebido por linha de comando
parser.add_argument("number")
#essa chamada faz com que os parâmetros recebidos pelo programa sejam guardados no objeto args
args = parser.parse_args()
#tipo a "função main" do programa
if __name__ == "__main__":
getArguments()Basicamente o código acima inicia-se no bloco if name == "main": (linha 15), chamando a função getArguments() (linha 16). A seguir, as linhas 6, 9 e 12 cumprem o papel de iniciar o parser, adicionar o parâmetro esperado (number) e retornar os parâmetros para args, respectivamente.
Vamos rodar o código por meio do comando python teste.py (lembrando que teste.py é o nome do arquivo em que você vai escrever seu código) e ver o que acontece?
Deu erro, pois o parâmetro number não foi passado na linha de comando.
O erro ocorrido é o seguinte: não foi passado o parâmetro number para o programa. Vamos informar um parâmetro dessa vez: python teste.py 6
Deu certo, ainda que nosso programa não faça nada de útil…
Vamos agora modificar o código acima para que o programa avalie se o número em questão é par ou ímpar?
import argparse
def getArguments():
parser = argparse.ArgumentParser()
parser.add_argument("number")
args = parser.parse_args()
#retorna os argumentos para o main
return args
if __name__ == "__main__":
args = getArguments()
#testo se o parâmetro em questão é divisível por 2. se for, é par, caso contrário, é ímpar
if (args.number % 2 == 0):
print("O número passado é par.")
else:
print("O número passado é ímpar.")Não estranhe, mas limpei um pouco o código para não desperdiçarmos linhas nesse tutorial =)
Enfim, observe a partir da linha 14 do código acima. Eu estou avaliando se, ao dividir args.number por 2, o resto é 0 (divisão inteira). Se for, o mesmo é divisível por 2 e, consequentemente, é par. Caso contrário, é ímpar. Só que, afinal de contas, o que é args.number?
Vocês notaram que, na linha 4, definimos um argumento em nosso programa chamado number? Pois então: acessamos os parâmetros que definimos no código em args (definido na linha 5) por meio do ponto final e do nome que atribuímos para aquele argumento. Os parâmetros se tornam atributos de args.
Só que se você testar o programa da forma como está, ele não funciona:
O erro ocorreu pois args.number não é do tipo inteiro.
O erro ocorre pois, por padrão, todo parâmetro recebido pelo programa por meio de argparse é do tipo string, se mais nada for especificado. Precisamos converter o parâmetro para inteiro e fazemos isso na mesma linha em que definimos esse novo argumento, adicionando type = int (linha 6).
import argparse
def getArguments():
parser = argparse.ArgumentParser()
#adicionamos o type = int abaixo
parser.add_argument("number", type = int)
args = parser.parse_args()
return args
if __name__ == "__main__":
getArguments()
if (args.number % 2 == 0):
print("O número passado é par.")
else:
print("O número passado é ímpar.")Agora sim, nosso programa funciona!
Tratamento de Erros!
Algo interessante de se empregar a argparse é que ela automatiza o tratamento de erros quando o usuário passa argumentos indevidos. Vamos, por exemplo, tentar passar “seis” ao invés do número 6 no código anterior:
A biblioteca argparse informa ao usuário que a informação “seis” não é do tipo inteiro.
Ao invés de dar erros imprevistos no interior do programa, a passagem de parâmetros pelo argparse já permite que a mesma “barre” a continuidade do programa caso o dado passado não seja do tipo esperado.
No exemplo acima, a palavra "seis" não é entendida como inteiro (nem pode ser convertida) e por isso o programa não deve continuar. Além disso, esse problema é informado devidamente ao usuário.
Contudo, podemos ser mais didáticos ainda!
Adicionando Informação de Ajuda
Quando você definir um novo parâmetro, é interessante você incluir no argumento algumas informações pertinentes a ele, por meio do campo help. Veja abaixo:
import argparse
def getArguments():
parser = argparse.ArgumentParser()
#note que agora adicionei o help abaixo!
parser.add_argument("number", help = "Número a ser informado que o programa verificará se é par ou ímpar. Lembre-se de informá-lo como do tipo int.", type = int)
args = parser.parse_args()
return args
if __name__ == "__main__":
getArguments()
if (args.number % 2 == 0):
print("O número passado é par.")
else:
print("O número passado é ímpar.")Perceba que, na linha 6, adicionamos uma informação de ajuda, explicando o papel daquele parâmetro em nosso programa. Ao rodar o código passando o parâmetro (-h), vemos que nossa explicação de ajuda é apresentada, facilitando bastante o entendimento de nossa aplicação pelo usuário.
Nosso parâmetro number é apresentado com um texto de ajuda ao lado.
Para concluir, algo interessante relacionado é adicionar a informação description no objeto argparse.ArgumentParser(), para que esteja descrito o que sua aplicação faz nessa tela de ajuda. Veja o código (linha 3) e o print abaixo para melhor entendimento.
import argparse
def getArguments():
parser = argparse.ArgumentParser(description="Esse programa verifica se um número é par ou ímpar.")
parser.add_argument("number", help = "Número a ser informado que o programa verificará se é par ou ímpar. Lembre-se de informá-lo como do tipo int.", type = int)
args = parser.parse_args()
return args
if __name__ == "__main__":
getArguments()
if (args.number % 2 == 0):
print("O número passado é par.")
else:
print("O número passado é ímpar.")Em destaque a descrição que explica o que o programa realiza.
Na tela de ajuda acima podemos ver que existem dois tipos de parâmetros: os posicionais (positionals) e opcionais (optionals). O que são eles? Onde vivem? Do que se alimentam?
Parâmetros Posicionais
Para resumir, os parâmetros posicionais são obrigatórios e sua ordem deve ser respeitada ao invocar o programa. Para fins de exemplo, vamos fazer outro script, agora para subtrair dois números:
import argparse
def getArguments():
parser = argparse.ArgumentParser(description="Esse programa computa a subtração de dois números.")
#configurei os parâmetros para a subtração
parser.add_argument("minuendo", help = "Primeiro valor da operação.", type = int)
parser.add_argument("subtraendo", help = "Segundo valor da operação.", type = int)
args = parser.parse_args()
return args
#tipo a "função main" do programa
if __name__ == "__main__":
args = getArguments()
print("Minuendo:", args.minuendo)
print("Subtraendo:", args.subtraendo)
#resultado da operação
print("Resultado:", args.minuendo - args.subtraendo)Programa após a execução do comando python teste.py 6 4.
No exemplo acima, o 6 é o parâmetro minuendo definido na linha 6 do código, enquanto o valor 4 é o subtraendo (linha 7). Nesse caso, a ordem em que as informações são passadas por linha de comando é fundamental e caso falte algum deles, ocorrerá erros.
Viu? Sem todos os parâmetros posicionais passados, o programa dá erro.
Talvez você esteja pensando em uma coisa: e se eu precisar passar múltiplos valores de um mesmo tipo? E se eu não sei de antemão quantos são?
Para isso, uma boa solução é o campo nargs.
Nargs?
O campo nargs define quantos elementos, de um mesmo tipo, um parâmetro do seu programa pode receber de uma só vez.
Para entender isso, vamos criar um programa que soma um número variável de valores inteiros. Podem ser 2, 3 ou mesmo 20.
Para tal, o programa conterá um único argumento a ser recebido, mas introduzindo o campo nargs (linha 6).
import argparse
def getArguments():
parser = argparse.ArgumentParser(description="Esse programa soma vários números.")
#adicionado o parâmetro nargs com o símbolo +, que diz que um ou mais valores do tipo inteiros podem ser recebidos por aquele argumento
parser.add_argument("numbers", help = "Um ou mais valores inteiros passados.", nargs = '+', type = int)
args = parser.parse_args()
return args
if __name__ == "__main__":
args = getArguments()
#só pra gente verificar todos os elementos que fazem parte dessa lista
print(args.numbers)
#iteramos um laço para somar todos os elementos dentro de um acumulador
accumulator = 0
for eachInt in args.numbers:
accumulator += eachInt
#mostramos a soma final
print("Soma final:", accumulator)Após passar os parâmetros 6, 7 e 8, temos que eles são guardados numa lista dentro de args.numbers e somados posteriormente.
No código acima, podemos ver que o valor atribuído para o campo nargs foi o +, que indica que um ou mais valores serão informados para aquele mesmo argumento. Outras possibilidades podem ser usadas em nargs, como pode ser visto na tabela abaixo.
Um número qualquer (nargs=N):
Espera-se que o número exato de elementos informados seja passado.
Exemplo: Se for passado
nargs=3, espera-se receber 3 elementos.
Asterisco (nargs=*):
Funciona de maneira parecida com
nargs=+, mas com algumas diferenças:Não gera erros se nenhum parâmetro for passado.
Pode aceitar zero ou mais parâmetros.
Um caso que merece atenção em particular é o nargs=?. Ele tentará consumir o elemento como um único item, se ele for passado. Se nada for informado, ele deixará de ser obrigatório e atuará como um parâmetro opcional.
Para ilustrar isso, veja o código abaixo (principalmente na linha 3).
import argparse
parser = argparse.ArgumentParser(description="Esse programa poderá receber um inteiro ou não.")
parser.add_argument("something", help = "Um inteiro poderá ser recebido ou não.", nargs = '?', type = int)
args = parser.parse_args()
print("Parâmetro passado:", args.something)Veja o efeito ao passar nenhum, 1 ou 2 parâmetros:
Quando nenhum valor é passado, o argumento args.something será vazio, do tipo None. Ao informar um valor, ele o guardará e tudo funcionará corretamente. Informando dois valores, o mesmo dará erro, pois somente um era esperado.
Ao não passar parâmetro algum, o elemento args.something passa a não conter nada e se torna uma espécie de parâmetro opcional, só que obrigado a ser inserido em uma ordem específica.
Se um elemento é passado, ele é armazenado dentro de args.something (por exemplo, o 6).
Finalmente, quando mais de um elemento é informado, um erro ocorre, pois ainda é um único argumento definido no código.
Há usos mais avançados para ele, mas que fogem do escopo desse tutorial. Se vocês quiserem que eu aborde futuramente esses pontos, comentem embaixo pra eu saber e produzir outros textos!
Parâmetros Opcionais
Como o próprio nome sugere, esses argumentos podem ser usados pelo usuário ou não, a sua escolha. Eles não impedem o programa de "rodar" quando não são consumidos.
import argparse
def getArguments():
parser = argparse.ArgumentParser(description = "Esse programa recebe dois argumentos: um obrigatório e outro opcional.")
#configurei dois parâmetros
parser.add_argument("obrigatorio", help = "Parâmetro obrigatório a ser passado.")
parser.add_argument("--opcional", help = "Parâmetro opcional a ser passado.")
args = parser.parse_args()
return args
if __name__ == "__main__":
args = getArguments()Rodei o programa acima duas vezes: uma sem passar qualquer parâmetro e outra informando o parâmetro obrigatório. Só a segunda tentativa “rodou”.
Perceba no código acima que a diferença entre o parâmetro obrigatório (definido na linha 6) e o opcional (linha 7) são apenas os tracinhos (–). Um parâmetro pode ser definido como opcional quando possuir um “-” ou “–” (explicarei a diferença entre o uso desses traços ao longo do texto, mas a existência deles define se o mesmo será posicional ou opcional).
Na figura acima, rodei o programa duas vezes: em uma não passei o parâmetro obrigatorio (python teste.py), o que ocasionou erro. Na segunda tentativa (python teste.py exemplo) o parâmetro args.obrigatorio recebe o valor "exemplo".
Similarmente com o que ocorre nos argumentos posicionais, o acesso ao parâmetro opcional no interior do código é feito por meio de args.opcional.
Talvez você esteja intrigado com os tracinhos. Por que você pode usar apenas "-" ou "--"? É que, normalmente, usamos um único tracinho para referirmos aos argumentos com uma única letra e, no caso de dois tracinhos, uma palavra completa. É uma questão de padrão adotado em muitos softwares. Veja o exemplo abaixo:
import argparse
def getArguments():
parser = argparse.ArgumentParser(description = "Esse programa recebe um número e apresenta seu quadrado.")
parser.add_argument("-n", "--numero", type = int, help = "Número a ser passado.")
args = parser.parse_args()
return args
if __name__ == "__main__":
args = getArguments()
if (args.numero is None):
print("Nenhum número foi passado.")
else:
print("Resultado:", args.numero * args.numero)No programa acima ocorre o seguinte: se eu passar um inteiro, ele vai me mostrar o quadrado desse valor. Se nada for informado (verificado na linha 10), então será mostrado na tela que nenhum número foi atribuído na execução do código (linha 11). Caso contrário, o valor será apresentado (linha 13).
Perceba que ao declarar o parâmetro (linha 4), eu defini duas formas do usuário informar em linha de comando esse argumento: -n ou --numero. O usuário pode escolher o que preferir, como podemos ver nas execuções abaixo.
No entanto, não se pode esquecer que é preciso usar a notação -n ou --numero antes de informar o valor do argumento opcional durante chamado por linha de comando (veja abaixo).
Rodei o programa 3 vezes: em uma não passei nada, na segunda vez informei o valor 6 pelo comando -n e, na última vez, passei por –numero. As duas últimas funcionaram de maneira idêntica.
default
Quando o assunto são argumentos opcionais, acho conveniente explicar o campo default, que atribui um valor padrão para um parâmetro que não tiver valor especificado.
Posso simplificar o programa acima, fazendo com que ao rodar o programa sem informar o valor do parâmetro opcional, o mesmo seja preenchido com o valor padrão zero automaticamente.
import argparse
def getArguments():
parser = argparse.ArgumentParser(description = "Esse programa recebe um número e apresenta seu quadrado.")
#após introduzir o campo default, se eu omitir seu uso, o código assumirá que args.numero será preenchido com o default zero
parser.add_argument("-n", "--numero", type = int, default = 0, help = "Número a ser passado.")
args = parser.parse_args()
return args
if __name__ == "__main__":
args = getArguments()
print("Resultado:", args.numero * args.numero)Observe que quando o parâmetro opcional –numero é omitido, o mesmo é preenchido automaticamente com zero.
dest
Pode ser que você não queira que o nome do argumento dentro do código seja igual ao nome dado para o parâmetro usado na linha de comando.
O campo dest permite que o nome do atributo que guarda o valor do parâmetro passado seja diferente do nome dado a ele em linha de comando.
Veja o programa abaixo que armazena a soma de vários números.
import argparse
def getArguments():
parser = argparse.ArgumentParser(description = "Esse programa realiza a soma de vários números.")
#observe a introdução do campo dest aqui
parser.add_argument("-n", type = int, dest = "numbers", nargs = '+', help = "Recebe o conjunto de números a serem somados.")
args = parser.parse_args()
return args
if __name__ == "__main__":
args = getArguments()
#realiza a soma de todos os números
accumulator = 0
#veja que eu pude me referir a args.numbers
for eachValue in args.numbers:
accumulator += eachValue
print("Soma total:", accumulator)Assim sendo, é possível "renomear" um argumento para outro nome que seja mais apropriado no interior do código.
Na linha 18 foi possível referir-se ao parâmetro por meio de args.numbers, pois o campo dest foi incluído na definição do mesmo (linha 6).
action
Ao trabalhar com parâmetros, estes podem disparar ações com relação a forma como aquele dado será tratado pelo parser de argumentos. Isso é informado dentro da função add_argument(), por meio do campo action.
Por padrão, os argumentos criados sem informar o action recebem action = 'store', o que indica que o mesmo será armazenado e convertido para o tipo apropriado, se informado (caso contrário, o mesmo será salvo como string).
Uma forma de se criar uma flag booleana (um parâmetro que recebe apenas sim ou não, verdadeiro ou falso) pode ser definida por meio do action = 'store_true'.
import argparse
def getArguments():
parser = argparse.ArgumentParser(description = "Esse programa verifica se um número é par ou ímpar. Há um parâmetro opcional para analisar se o número é múltiplo de 3.")
parser.add_argument("numero", type = int, help = "Número a ser passado.")
#a flag abaixo receberá verdadeiro (1) se for chamada
parser.add_argument("-m", "--multiploDe3", help="Se essa flag for usada, então o programa dirá se o número passado é múltiplo de 3", action="store_true")
args = parser.parse_args()
return args
if __name__ == "__main__":
args = getArguments()
if (args.numero % 2 == 0):
print("Número é par.")
else:
print("Número é ímpar.")
#se a flag definida na linha 6 for usada, entra no if
if (args.multiploDe3 == True):
#número é múltiplo (divisível) por 3? se for, entra
if (args.numero % 3 == 0):
print("Número é múltiplo de 3.")
else:
print("Número não é múltiplo de 3.")No programa acima, eu continuo informando um parâmetro posicional para dizer se o valor é par ou ímpar (linha 4). No entanto, existe uma flag -m (ou --multiploDe3) que recebe verdadeiro se ela for usada na linha de comando. Se isso ocorrer, o programa irá verificar se o número é múltiplo de 3. Caso contrário, não mostra.
Veja como o action = "store_true" foi inserido (linha 6) para ocasionar esse efeito.
O programa acima foi executado 4 vezes. Sem o parâmetro (-m), o programa não mostra se o número é ou não é múltiplo de 3. O efeito é sinônimo caso seja passado o argumento (–multiploDe3).
Convém dizer que também existe o store_false, que por padrão define que o valor do parâmetro opcional será falso, caso seja usado na linha de comando. No mais, exceto por esse detalhe, seu uso é idêntico ao store_true.
action = “store_const”
Uma outra possibilidade para action é o valor store_const que é similar ao store_true, mas que pode assumir valores além do verdadeiro ou falso. Por exemplo, considere o programa abaixo.
import argparse
def getArguments():
parser = argparse.ArgumentParser(description = "Esse programa informa a resposta para a vida, o universo e tudo mais (mas para isso é necessário informar o parâmetro opcional que usa store_const).")
#parâmetro opcional com store_const
parser.add_argument("-a", "--answer_life_universe_everything", action = "store_const", const = 42)
args = parser.parse_args()
return args
if __name__ == "__main__":
args = getArguments()
#imprime o valor constante do argumento opcional se ele for passado
if args.answer_life_universe_everything is not None:
print(args.answer_life_universe_everything)
else:
print("Nada foi passado")No exemplo acima, rodamos o algoritmo duas vezes: sem e com o parâmetro definido na linha 6. Assim sendo, o store_const é similar ao store_true, podendo fixar o valor do argumento args.answer_life_universe_everything para o que quiser.
No entanto, é importante perceber que o action = store_const deve ser usado em conjunto com const, para que seja atribuído o valor que esse atributo receberá (linha 6).
action = “version”
Existem outros tipos de valores para o campo action, como “append“, “count” e até mesmo outros surgidos recentemente. Saiba mais sobre eles aqui (de repente posso até estender esse texto no futuro adicionando eles). No entanto, como o foco do texto é introdutório, acho importante mencionar um bastante usado que é o version.
Basicamente ele é usado para atribuir e apresentar, de maneira padronizada, a versão atual do seu programa. Peguemos o exemplo anterior adicionando essa funcionalidade:
import argparse
def getArguments():
#note que adicionei outro campo aqui: prog, explico abaixo a importância dele em consonância com o action="version"
parser = argparse.ArgumentParser(prog='VIDA, VERDADE E O UNIVERSO', description = "Esse programa informa a resposta para a vida, o universo e tudo mais (mas para isso é necessário informar o parâmetro).")
parser.add_argument("--answer_life_universe_everything", action = "store_const", const = 42)
#adicionei o parâmetro opcional referente a versão do software em questão
parser.add_argument("-v", action = "version", version='%(prog)s 42.0')
args = parser.parse_args()
return args
if __name__ == "__main__":
args = getArguments()
if args.answer_life_universe_everything is not None:
print(args.answer_life_universe_everything)
else:
print("Nada foi passado")Esse parâmetro obrigatório apenas imprime qual a versão atual do seu programa: se ele é beta (normalmente abaixo do 1.0), se é 2.0, 3.0., etc. No caso aqui, ele é 4.2 =). Ele está definido na linha 8.
Observe que eu precisei adicionar o campo prog = na linha 4, quando eu defino o objeto responsável por extrair as informações (parser). Fiz isso pois PROG = é uma forma de se definir o nome do programa criado.
Isso é necessário para, por exemplo, ao invocar o argumento opcional -v, seja mostrado não apenas a versão do programa, mas também o nome a ele atribuído junto com a versão.
Dessa forma, temos uma maneira padronizada de informar ao usuário a atual versão da aplicação criada.
Combinando Parâmetros Obrigatórios e Opcionais
Vamos agora tentar usar boa parte dos conceitos anteriores em um mesmo programa. Suponha, por exemplo, que criamos um script cujo objetivo é computar uma equação de segundo grau:
Nessa aplicação tanto a, quanto b e c são parâmetros recebidos por linha de comando. Para ilustrar o uso de um argumento opcional, vamos assumir que b e c sejam opcionais, de forma que quando não são usados, estes serão assumidos como 0.
Como ficaria o código desse software?
import argparse
#importei para usarmos a função que computa raiz quadrada
import math
def getArguments():
parser = argparse.ArgumentParser(description = "Esse programa computa as raízes de uma equação de segundo grau.")
#defini 3 argumentos, dos quais apenas o primeiro é obrigatório (já que a deve ser diferente de 0)
parser.add_argument("a", type = int, help = "Valor a (ax^2).")
parser.add_argument("-b", type = int, default = 0, help = "Valor b (bx).")
parser.add_argument("-c", type = int, default = 0, help = "Valor c.")
args = parser.parse_args()
return args
if __name__ == "__main__":
args = getArguments()
#computa raiz quadrada (b^2 - 4ac)
delta = args.b * args.b - 4 * args.a * args.c
#de acordo com o delta, verificamos quantas raízes a equação possui
if delta < 0:
print("A equação não possui raízes reais.")
elif delta == 0:
#uma raiz real
raiz = (0 - args.b) / (2 * args.a)
print("Raiz:", raiz)
else:
#duas raízes reais
raiz1 = (0 - args.b) + math.sqrt(delta) / (2 * args.a)
raiz2 = (0 - args.b) - math.sqrt(delta) / (2 * args.a)
print("Raizes:", raiz1, raiz2)Existem várias formas possíveis de se implementar o algoritmo acima, mas optei pelo parâmetro a ser obrigatório (já que numa equação de segundo grau, apenas a, obrigatoriamente, é diferente de 0) enquanto o b e o c são opcionais (se não forem passados, assume-se o valor 0).
Nas linhas 10, 11 e 12 foram definidos os argumentos obrigatórios e opcionais. Quanto as linhas 24 a 35, estas computam as raízes da equação de segundo grau passada, caso existam. Uma explicação, bem como cálculos feitos pro exemplo abaixo podem ser vistos nessa página.
Quatro exemplos para a aplicação apresentada acima, considerando várias possibilidades: sem raízes reais, com uma raiz e duas raízes reais.
Conclusão
Muito mais poderia ser falado sobre essa biblioteca, mas acredito que com esse texto foi possível fazer uma exposição dos elementos essenciais para um bom uso da ferramenta.
Espero que tenham gostado do texto e sugiram outros para que eu possa explicar melhor aqui.
Grande abraço e até a próxima!






















