Neste curso, você aprendeu a fazer alguns programas simples: imprimir certos termos, separar valores em uma string, extrair substrings de uma string maior, gerar listas. Não são programas suficientemente complexos para resolver problemas reais, mas são um passo nesse sentido, pois você está aprendendo sobre os elementos que efetivamente compõem os programas como:

  1. variáveis
  2. expressões condicionais
  3. iteradores
  4. listas

No caminho de desenvolver programas realmente úteis, o primeiro passo é você aprender a definir funções.

No primeiro módulo, você aprendeu a usar funções para estabelecer comandos executáveis. Até agora, usamos apenas as funções nativas do Python, que são funções contidas no próprio código da linguagem. Neste módulo, você aprenderá a desenvolver novas funções, a partir dos elementos que você já conhece e aprenderá a agrupar funções dentro de um módulo.

1. Funções

1.1 Definindo funções

Você já aprendeu que não é possível explicar para o Python o significado abstrato de uma variável: o que você pode fazer é atribuir um valor a um nome, o que faz com que esse nome sirva como uma variável.

Com as funções ocorre a mesma coisa: você cria funções por meio da definição de que um certo nome corresponderá a um conjunto de instruções, por meio da utilização da função def.

def curso():
	print ('Este é o módulo final do curso Python Para Juristas')

Esse código define como a função curso() o comando de imprimir o texto acima. Note que, se você copiar esse código para o seu Editor e executá-lo, a frase não será impressa porque ele faz uma definição de função, mas não faz um function call, ou seja, não instrui o interpretador a executar a função definida.

Já o código abaixo tem uma definição de função e um comando para que ela seja executada, motivo pelo qual a frase definida aparecerá no seu console.

def curso():
	print ('Este é o módulo final do curso Python Para Juristas')

curso()

Repare que o nome da função definida não é curso, mas curso(), porque toda função que você definir precisa ter esses parênteses, sob pena de você receber um SyntaxError, já que a sintaxe da definição das funções exige esses parênteses porque, dentro dele, você precisa indicar as variáveis que precisam ser definidas para que que a função possa gerar um comando executável.

1.2 Funções, variáveis e parâmetros

Neste caso específico, não há variáveis, pois você instrui a impresão de uma string predefinida. Porém, esse não é o caso padrão, porque as funções que você define normalmente instruem comandos que utilizam certas variáveis.

def curso(modulo):
	print ('Este é o módulo ' + modulo + ' do curso Python Para Juristas')
    
curso('4')

Nesse caso, a string a ser impressa utiliza o valor da variavem modulo, que funciona como parâmetro da função. Parâmetros são os elementos que vêm entre parênteses e que você precisa fornecer toda vez que chama a função, para que a combinação funções + parâmetros possa constituir um comando executável, tal como:

# definição da função, com o parâmetro modulo
def curso(modulo):
	print ('Este é o módulo ' + modulo + ' do curso Python Para Juristas')
  
#chamada da função com o argumento '4'
curso('4')

Observe que o parâmetro da função curso() é necessariamente uma string, pois usamos como parâmetro do print() uma concatenação de strings. Se você quiser deixar essa função mais robusta (ou seja, menos sujeita a gerar erros), é possível inserir dentro do print o comando str(modulo), pois isso permitirá que você insira também outros tipos de variáveis (como as numéricas) como argumento da função módulo.

Embora essa distinção não seja sempre respeitada nos textos sobre Python, há uma diferença entre parâmetro (que são as variáveis que compõem as funções definidas, e devem vir entre parênteses no momento do uso do def) e argumento (que são os valores que você define concretamente no momento em que faz o function call).

1.3 função input()

Este é um bom momento para você aprender uma nova função, que permite a introdução de novos valores pelos usuários do programa: input(). Essa função opera conferindo valor a uma variável que você definiu, como na linha 2 do código abaixo:

# define que uma variável textoinformado será preenchida pelo usuário, como input
textoinformado = input('Insira o número do módulo:  ')

# definição da função, com o parâmetro modulo
def curso(modulo):
    print('Este é o módulo ' + str(modulo) + ' do curso Python Para Juristas')
  
#chamada da função com o argumento o valor da variável modulo
curso(textoinformado)

Observe que a sintaxe do input funciona assim: você define o input() como valor de uma variável, e como argumento do próprio input() você coloca a frase que quer que apareça no console. É no console que os programas são efetivamente executados e e lá que você tem de dar o input (no editor, você edita algoritmos, mas não executa nada).

1.4 Função com múltiplos parâmetros

Você pode ter uma função com vários parâmetros, dependendo da complexidade das instruções a serem executadas. Nos módulos anteriores, trabalhamos a estratégia de extrair um texto de uma string, a partir de um marcador de início e um marcador de fim. Por se tratar de uma instrução que é repetida exaustivamente em nossos programas, é muito útil criar uma função para que você possa repetir essa lógica com um comando apenas.

Que parâmetros precisamos definir para essa função de extração? Se você refletir com cuidado, deve concluir que são 3:

  1. string na qual se deve buscar o texto a a extrair
  2. marcador de início
  3. marcador de fim.

Com esses três parâmetros, você pode definir uma função como:

# define função extrair
def extrair(string, marcador_de_inicio, marcador_de_fim):
    inicio = string.find(marcador_de_inicio)
    fim = string.find(marcador_de_fim, inicio)
    texto = string[inicio + len(marcador_de_inicio):fim]
    print (texto)
    
# atribui valor à variável informacoes
informacoes = 'ADI2343242, Relator: Rosa Weber, Requerente: Indefinido, Requerido: não consta'
        
# function call
extrair(informacoes, 'Relator:',',')

A lógica dessas instruções já foi definida no módulo anterior. Neste momento, trata-se apenas de gerar uma função com as cuja estrutura você já conhecia.

Veja que todos os parâmetros que você definir devem ser usados dentro das instruções que compõem a função. Se você não fizer isso, o Python vai te avisar que há um parâmetro definido, mas não usado.

1.5 Isolamento do processamento das funções

Se você tiver a curiosidade de observar o seu Variable Explorer, notará uma coisa curiosa: não aparecem neles os parâmetros da sua função. Isso ocorre porque todo o processamento das funções ocorre de uma maneira independente, que não interfere com o conteúdo das variáveis do seu programa.

Tal como ocorre em certas festa, o que acontece no processamento da função, permanece na função e não passa para o seu programa. Esse isolamento é útil especialmente porque pode acontecer de a função usar certas variáveis que vão ter o mesmo nome de variáveis do seu programa, o que acarretaria uma reação em cadeia indesejada. Imagine, por exemplo, que reescrevêssemos o código do item 1.3, acima, chamando de modulo a variável que nele constava como textoinformado:

# define que uma variável textoinformado será preenchida pelo usuário, como input
modulo = input('Insira o número do módulo:  ')

# definição da função, com o parâmetro modulo
def curso(modulo):
    print('Este é o módulo ' + str(modulo) + ' do curso Python Para Juristas')
    modulo = 25
  
#chamada da função com o argumento o valor da variável modulo
curso(modulo)

Se você executar esse código e inserir como input 4, o resultado da function call utilizará o argumento 4, e não o valor 25, que foi definido para a variável módulo dentro da função.

A vantagem desse isolamento é justamente essa: quando você usa funções feitas por outras pessoas, você não sabe quais sãos as variáveis utilizadas dentro delas, mas isso não é um problema porque, mesmo que usem variáveis com nomes bastante comuns (a, x, nome, number, n, etc.), você não precisa se preocupar com o modo como esses valores vão interagir com o seu código.

Por outro lado, você deve sempre ter em mente que não adianta criar variáveis dentro de um código e  depois tentar utilizar esses valores no seu programa. Ocorre, porém, que muitas vezes é exatamente isso o que você quer: gerar funções que gerem alguns valores específicos. O nosso modo de romper esse isolamento é introduzir dentro da sua função o elemento return().

1.5 Return()

O return() permite que valores gerados dentro de uma função sejam atribuídos a variáveis do seu programa. Isso é mais fácil de ser compreendido por um exemplo, modificando um pouco a nossa função de extração, trocando o print (texto) por return(texto).

Isso aprimora a nossa função porque, de fato, não queremos imprimir um texto na tela, mas queremos extrair as informações relevantes e atribuí-las a variáveis que possam ser trabalhadas: arquivadas em listas, processadas por outras funções, gravadas em arquivos, etc.

No código abaixo, tomamos a função extrair e acrescentamos um return(), de forma que podemos atribuir o resultado da função a certas variáveis, que depois inserimos em uma lista. Esse código vai ficando maior e mais complexo, mas já temos um programa capaz de resolver um problema prático.

# define função extrair
def extrair(string, marcador_de_inicio, marcador_de_fim):
    inicio = string.find(marcador_de_inicio)
    fim = string.find(marcador_de_fim, inicio)
    texto = string[inicio + len(marcador_de_inicio):fim]
    return (texto)
    
# atribui valor à variável informacoes
informacoes = 'Processo: ADI5000, Relator: Rosa Weber, Requerente: Governador de SP, Resultado: Prejudicado'
        
# cria uma lista para arquivar os dados extraídos
lista_de_dados = []

# atribui valor às variáveis escolhidas
processo = extrair(informacoes, 'Processo:', ',')
relator = extrair(informacoes, 'Relator:', ',')
requerente = extrair(informacoes, 'Requerente: ', ',')

# insere os dados na lista
lista_de_dados.append(processo)
lista_de_dados.append(relator)
lista_de_dados.append(requerente)

print (lista_de_dados)

Extrair esses dados da lista acima é fácil, pois é uma lista de dados previamente organizados, limpos e numa ordem clara. Porém, um programa com essa mesma estrutura (adaptando apenas os marcadores de início e de fim) é capaz de extrair os dados das informações processuais reais, fornecidas pelo STF, na forma longas strings. A habilidade de fazer essa extração real será trabalhada no início dos módulos de Data Mining Judicial, para a qual este curso introdutório ao Python prepara vocês.

1.6 Criando módulos

Uma vez que você cria uma função interessante, é bem provável que você não queira usá-la somente no programa que você está fazendo, mas também em outros.

Uma boa função de extração será usada, por exemplo, será provavelmente usada em vários programas e, por esse motivo, você pode gravá-la em um módulo de funções, que poderão ser carregadas em outros programas. Como fazer isso?

Primeiro, é preciso ter uma função a ser gravada. Tomemos, por exemplo, a função de extração desenvolvida acima. Crie um novo arquivo no Spyder e cole nele a função abaixo.

# define função extrair
def extrair(string, marcador_de_inicio, marcador_de_fim):
    inicio = string.find(marcador_de_inicio)
    fim = string.find(marcador_de_fim, inicio)
    texto = string[inicio + len(marcador_de_inicio):fim]
    return (texto)

Salve o arquivo, nomenando-o como modulo.py. Está criado o seu primeiro módulo, composto por uma função.

Observe que o Spyder deve ter gravado o modulo.py no seu diretório de trabalho (working directory), que é a pasta que você define previamente como local de gravação padrão dos seus arquivos. Você pode fazer isso no menu Tools: Preferences, que pode ser acessado pelo símbolo da chave de fenda nos botões do seu menu.

Eu uso o C:/Python como diretório de trabalho, mas você pode escolher qualquer pasta no seu computador. Facilita a sua vida, especialmente nesse início, que todos os programas fiquem nesse diretório porque você poderá importar as funções dos módulos gravados nele com uma função muito simples:

from modulo import extrair

Uma vez importada a função, você pode usá-la no seu programa, sem ter de repetir os seus termos. Porém, todas as funções do módulo extrair deverão ser referidas dentro do programa como modulo.nomedafunção (no caso modulo.extrair).

Usando esse módulo, nosso programa anterior poderia ser reescrito como:

# importa modulo
import modulo
    
# atribui valor à variável informacoes
informacoes = 'Processo: ADI5000, Relator: Rosa Weber, Requerente: Governador de SP, Resultado: Prejudicado'
        
# cria uma lista para arquivar os dados extraídos
lista_de_dados = []

# function call: funcão + argumentos
processo = modulo.extrair(informacoes, 'Processo:', ',')
relator = modulo.extrair(informacoes, 'Relator:', ',')
requerente = modulo.extrair(informacoes, 'Requerente: ', ',')

# insere os dados na lista
lista_de_dados.append(processo)
lista_de_dados.append(relator)
lista_de_dados.append(requerente)

print (lista_de_dados)

Você logo terá um módulo que não tem apenas uma função mas várias, desenvolvidas especialmente para os nossos programas de data mining (extratores de dados e geradores de bancos de dados):

  • função de extração de dados
  • função de gravação
  • função de abrir arquivos
  • função de gerar tabelas

De fato, disponibilizaremos para você as funções desenvolvidas no curso, em um módulo que vocês poderão utilizar nos seus próprios programas, importando as funções que vocês desejarem.

Em vez de importar os módulos, você pode importar diretamente as funções, de tal forma que elas possam ser referidas apenas pelo seu nome.Para isso, você pode usar um comando do tipo:

from modulo import extrair

Com isso, você não importaria o módulo (com todas as suas funções), mas uma função específica (que manteria o seu próprio nome). Com isso, você poderia continuar usando no programa apenas o nome extrair, em vez do modulo.extrair.

1.7 Pacotes e Bibliotecas

Uma vez que um módulo seja suficientemente desenvolvido, ele pode ser composto por várias funções complexas, capazes de resolver bem o problemas de um determinado campo (data mining, estatística, visualização de dados, etc.).

Uma vez que esse desenvolvimento esteja amadurecido, o desenvolvedor normalmente conta com alguns módulos especializados, que podem ser consolidados na forma de um pacote (package), que é uma coleção de módulos organizados de uma forma determinada, para que eles possam ser importados conjuntamente.

Just like the use of modules saves the authors of different modules from having to worry about each other’s global variable names, the use of dotted module names saves the authors of multi-module packages like NumPy or Pillow from having to worry about each other’s module names. (Python Tutorial: Modules)

Uma vez que esses pacotes sejam publicados  (normalmente no Python Package Index (PyPI)), eles passam a ser chamados pelo nome genérico de bibliotecas (libraries). Biblioteca pode ser um módulo, um pacote ou um conjunto de pacotes, a depender de seu tamanho e complexidade. Porém, ele deve estar organizado de tal forma que você pode instalá-lo no seu computador, o que permitirá a sua importação para os seus programas.

Lembre-se: instalar um módulo ou um pacote faz com que eles estejam disponíveis para os seus programas, mas é sempre necessário importar o módulo ou a biblioteca, para que as suas funções sejam executáveis dentro de um programa específico.

Em breve, você se acostumará com importar algumas das bibliotecas de Python mais usadas: pandas, os, time, beautifulsoup, etc. Essas bibliotecas são fruto do trabalhos de programadores (como você!), que disponibilizam seu trabalho para outras pessoas utilizarem, normalmente utilizando licenças que permitem o uso e modificação dos programas, contribuindo para a construção coletiva de novos desenvolvimentos.

1.8 PIP

Para instalar pacotes (packages) no Python, você conta com uma ótima ferramenta: pip. O pip já vem instalado no Anaconda e, com isso, você pode instalar novos pacotes a partir do console do Spyder ou prompt de comando.

Por exemplo, se você quiser instalar a biblioteca arrow, que lida com datas, basta inserir o comando:

pip install arrow

Como saber isso? Quando você encontra uma biblioteca em python, ela provavelmente fará parte da Python Package Index (PyPI), o que significa que ela pode ser instalada via pip. Quando você abre a página de uma dessas bibliotecas, uma das primeiras coisas que aparece é justamente o comando de instalação, inclusive com um botão que já copia o comando para a sua área de transferência.

Assim, quando você encontrar na internet indicações de que uma determinada biblioteca contém funções adequadas para o seu programa, basta fazer a sua instalação.

Lembre-se: instalar a biblioteca é um passo necessário para utilizá-la (embora várias já estejam instaladas via Anaconda), mas para usar a função dentro de um programa específico, é preciso importar o módulo ou pacote para o seu programa.

1.9 Github

O começar a desenvolver projetos, você fatalmente entrará em contato com a plataforma github.com, que é voltada a hospedar programas, que usam a ferramenta como sistema de controle de versão.

O controle de versão é uma funcionalidade importante no desenvolvimento de software, pois ele permite a introdução controlada de inovações no seu código, mantendo uma memória das mudanças e possibilitando um desenvolvimento colaborativo.

O github funciona como um repositório tanto de programas quanto de bases de dados. Veja, por exemplo, o excelente site da Johns Hopkins que consolida dados sobre a covid:

COVID-19 Dashboard by the Center for Systems Science and Engineering (CSSE) at Johns Hopkins University (JHU)

Se você olhar no centro da tela, na parte de baixo, encontrará um link para as bases de dados consolidadas, que foram disponibilizadas no GitHub, onde você pode fazer o download de um conjunto bastante amplo de dados sobre infecções e mortes causadas pela Covid-19 ao redor do mundo.

Um programa que está no Github pode ser baixado e você pode apresentar propostas de aprimoramento ou desenvolvimento. Assim, vale a pena você criar sua conta no GitHub, para poder ter um acesso facilitado a essas funcionalidades e para participar do desenvolvimento colaborativo dos códigos da disciplina.

Inclusive, é neste site que está o módulo dsd.py, que utilizaremos nos programas desenvolvidos na disciplina. Há duas formas simples de baixar arquivos do projeto dsd.

A primeira é entrar no repositório e clicar no botão verde 'Code', que abre uma opção de fazer o 'Download ZIP', que baixará todos os arquivos.

Também há uma forma de baixar apenas um arquivo, mas ela é menos evidente. Basta clicar no nome do arquivo que se quer baixar (no caso, o dsd.py) que somos levados para a página do arquivo. Nela, existe uma opção Raw, que abre uma página com o texto do código.

A página raw contém apenas o código bruto e não há um botão de salvar. Porém, se você clicar no texto com o botão direito do mouse, pode escolher 'Salvar Como' (Ctrl-S), o que possibilita salvar o arquivo dsd.py em qualquer diretório que você desejar. Sugerimos que você o salve no seu diretório de trabalho, ou no diretório em que você pretende gravar os arquivos com os programas a serem desenvolvidos na disciplina.