Programação | Python — Parte 2

Mais detalhes sobre uma das linguagens de programação mais utilizadas no mundo

Fernando Matsumoto
Turing Talks
10 min readMay 26, 2019

--

Na semana passada, passamos o básico da linguagem de programação Python. Introduzimos conceitos básicos como variáveis, atribuições e operações, assim como print, input e listas. Nesta semana, o nosso objetivo é terminar essa introdução, introduzindo conceitos como loops e funções. Poderemos então utilizar esses novos conhecimentos para explorar as áreas de Data Science e Machine Learning.

Função range

Existe uma função range(a,b,c) em Python que cria uma sequência de números automaticamente¹, sendo apenas necessário identificar o início a, o fim b e o passo c. Os números começam em a e aumentam até atingirem b (note que b não é incluído na sequência). O passo c é a diferença entre números consecutivos nessa sequência. Por exemplo:

Mais formalmente, a função range pode ser definida da seguinte maneira:

range(a,b,c) ≡ [a, a+1c, a+2c, a+3c, … ,❋] , ❋<b, ❋+c≥b.

Saiba que colocar apenas dois termos em range() fará com que o passo seja automaticamente igual a 1 (range(a,b) == range(a,b,1)), ou seja,

range(a,b) = range(a,b,1) ≡ [a, a+1, a+2, …, b-1].

Também é bom saber que dar à função apenas um número fará uma lista que começa em zero, tem passo igual a 1 e tem comprimento igual ao valor dado à função (range(a) == range(0,a,1)). Então:

range(a) = range(0, a, 1) ≡ [0, 1 ,2, …, a-1]

¹ Essa sequência de números se comporta como se fosse uma lista, mas há algumas diferenças. Por exemplo, não se pode adicionar números a essa sequência usando a função .append(). Para transformar essa sequência em uma lista, basta usar list(range(a,b,c)).

Loops (for, while)

Em Python, às vezes, é necessário realizar diversas operações repetitivas, como imprimir uma sequência de números consecutivos. Para esse tipo de tarefa, são utilizados loops.

Temos duas maneiras de executar um loop em Python. Podemos fazer utilizando um for, ou por meio de um while.

While loop: repete um bloco de código enquanto uma condição for verdadeira.

For loop: passa por todos os elementos de uma sequência, na ordem em que eles aparecem. No exemplo abaixo, o bloco dentro do for é executado uma vez para cada elemento da lista a.

Você também pode iterar utilizando a função range:

Caso seja necessário modificar a lista sobre a qual você está iterando, é necessário fazer uma cópia da lista. Isso pode ser feito utilizando a notação lista[:] vista acima.

Dicionários

Os dicionários são uma outra estrutura de dados nativa do Python. Esta estrutura é basicamente composta por elementos que possuem dois componentes: uma chave e um valor. Eles são a implementação, em Python, de hash tables. São extremamente úteis para diversas aplicações.

Um dicionário possui a seguinte estrutura:

dicionario = {key0:value0, key1:value1, key2:value2,..., keyN:valueN}

Como as listas, ele pode ser criado vazio ou já possuindo um ou mais elementos, como está mostrado no exemplo abaixo:

Para acessar os valores de um dicionário, usamos uma sintaxe parecida com as listas, utilizando os colchetes ([]), entretanto entre eles não vai o índice do elemento, e sim a sua chave.

Além disso, podemos iterar em um dicionário, utilizando o método keys() , que retorna um iterador de todas as chaves do respectivo dicionário. Um iterador é simplesmente um objeto no qual podemos iterar sobre, ou seja, pode ser uma lista ou uma tupla (será explicado adiante), por exemplo.

Utilizando os dicionários criados no exemplo anterior, vamos demonstrar estas funcionalidades:

Neste exemplo, apareceu algo que ainda não tínhamos visto, a função format() . Ela é muito útil para formatar strings, colocando valores de variáveis nos textos. Ela funciona da seguinte maneira: Ao criarmos a string, colocamos entre chaves ({}) os valores que serão substitúidos por variáveis. No exemplo acima, temos 'Chave do elemento: {c}' , isto é, {c} será substituído por alguma variável que queremos mostrar. Depois, para efetivamente substituirmos os valores, bastante aplicarmos a função format() , e referenciarmos os valores entre chaves em seus argumentos, como fazemos em format(c=key) . Poderíamos fazer 'A chave do elemento é {chave}.format(chave=key), por exemplo. (No Python 3.6 , há também as f-strings).

Uma aplicação desta estrutura poderia ser: Quero utilizar uma estrutura de dados para guardar diversas músicas, e para cada música, quero guardar o nome, a banda e o ano. O dicionário cai como uma luva, pois facilita a leitura, é intuitivo e é extremamente prático recuperarmos os dados guardados. A estrutura poderia ser facilmente construída da seguinte maneira:

Sim, o dicionário pode ser utilizado em conjunto com listas! Use sua criatividade para criar seus mixes de estruturas de dados de forma que seus dados possam ser acessados de forma eficiente e até para facilitar o entendimento do seu código para o outros programadores. A clareza do seu código é extremamente importante! (Procure sobre code readability).

Por fim, o dicionário é uma ótima estrutura de dados para armazenar dados. Em Python, é facilmente transformado num JSON, que é muito usado para envio e recebimento de dados.

Tupla

Como a última estrutura de dados apresentada neste tutorial, temos a tupla. A tupla é muito parecida com uma lista, porém é imutável. Visualmente, a única diferença é que uma lista é criada utilizando-se colchetes ([]), já a tupla é criada utilizando-se parênteses (()). Quando dissemos que esta estrutura de dados é imutável, isso quer dizer que, depois de criada, não pode ser mais alterada. Não é possível adicionar, remover ou alterar elementos.

Ela é uma estrutura mais rígida e segura, cujo objetivo é armazenar dados que devem ser manter inalterados ao longo do andamento do programa. Ela é usada, por exemplo, no funcionamento dos *args como você verá em breve.

Abaixo temos um exemplo de criação de tupla, seguido de tentativas de alterá-la.

Funções

Uma função é um bloco de código organizado e reutilizável que realiza uma certa ação. Para se criar uma função em Python, deve-se seguir a estrutura:

  • Blocos de função começam com a palavra def seguido do nome da função e de parênteses;
  • Qualquer input ou argumentos devem ser postos dentro dos parênteses;
  • A primeira linha de código após a definição costuma ser um comentário que explica o funcionamento da função;
  • O bloco de qualquer função começa com dois pontos (:);
  • A sentença return [expression] retorna o valor da função. O código return sem argumentos retorna o valor None.

Primeiro, usaremos apenas argumentos posicionais. Portanto, a ordem que os parâmetros da função são inseridos deve ser a mesma que foram declarados no argumento da função. Após a função ser criada, podemos chamá-la informando os argumentos e ela retornará o valor da expressão colocada no return. Vejamos alguns exemplos:

Exemplo 1

Neste primeiro exemplo, estamos criando uma função que printa o texto passado como argumento.

Exemplo 2

Neste outro exemplo, estamos criando uma outra função, que soma os dois argumentos passados a ela.

Todos argumentos em Python são passados por referência. Isso quer dizer que se você mudar um dos parâmetros dentro de uma função, a mudança também reflete na chamada na função. Exemplo:

Neste caso, mantivemos a referência do objeto passado e simplesmente anexamos valores no mesmo objeto. Isso produziria o resultado:

Os argumentos de uma função devem ser passados na ordem posicional correta. O número de argumentos na chamada da função deve ser igual ao número na definição da função (novamente, isso se deve pois estamos utiliznado argumentos posicionais. Na pŕoxima parte, explicaremos sobre outros tipos de argumentos).

As variáveis do programa podem não estar disponíveis em todas localizações do programa. Isso depende de onde a variável foi declarada. As variáveis podem ser locais ou globais.

Variáveis definidas dentro de uma função tem escopo local,e aquelas criadas fora da função tem escopo global. Dessa maneira, variáveis locais só podem ser acessadas dentro da função em que foram declaradas, enquanto as globais podem ser referenciadas por quaisquer funções.

Outros tipos de argumentos (padrão, *args e **kwargs)

Existem três outros tipos de argumentos que podemos utilizar em Python, além dos argumentos posicionais mostrados acima: são os argumentos padrão, *args e os **kwargs.

Argumentos padrão

Argumentos padrão são opcionais e têm um valor padrão caso não sejam passados. Por exemplo, para calcular o peso de um objeto, é necessário saber a massa e a aceleração da gravidade, que é aproximadamente g=9.80665 na Terra. Entretanto, sabemos que a aceleração da gravidade muda conforme a latitude, longitude e altura na Terra, mesmo que possa ser uma pequena variação.

Portanto, daremos ao usuário a liberdade de definir a sua própria aceleração da gravidade, isto é, a que ele julga mais precisa para calcular seu peso em sua dada situação. Dessa forma, podemos definir uma função peso, que recebe g como um argumento padrão.

Note que o argumento g pode ser passado tanto de forma posicional (peso(80, 10)), quanto nomeada (peso(80, g=10))

*args

O *args permite que passemos uma lista de argumentos para uma função, com número indefinido de termos. Dentro da função, recebemos exatamente a estrutura de dados n-tupla e podemos iterar nela a fim de executar os procedimentos da função.

Imagine um caso em que precisamos de uma função que receba uma quantidade indefinida de argumentos e execute alguma ação.

Podemos pensar numa função que recebe um ponto p0, cujas coordenadas são (x0, y0), e depois retorna um lista contendo as distâncias euclidianas entre p0 e uma série de pontos p1,…, pn, com n ≥ 1.

Primeiro, usaremos um argumento posicional p0 para receber o ponto p0 e depois utilizaremos o *args para capturar os outros pontos. Além disso, para deixar nosso código mais limpo, podemos declarar uma função auxiliar distance() que apenas calcula a disitância euclidiana entre dois pontos.

Assim, o código fica:

**kwargs

Lembrando novamente dos dicionários, utilizar **kwargs numa função é como se passássemos os argumentos para uma função em forma de dicionário. Com este tipo de argumento, não precisamos nos preocupar com a ordem dos argumentos (os argumentos são sempre nomeados) e nem em saber todos os possíveis argumentos. Podemos passar apenas os que nos interessam e deixar os outros indefinidos. Somando-se a isso, poderíamos permitir que o usuário passe um mesmo argumento utilizando nomes diferentes (o nome completo e sua abreviação, por exemplo).

Basicamente, quando uma função recebe **kwargs, ela recebe um dicionário de argumentos. Podemos verificar isso no exemplo abaixo:

É muito comum que ele seja usado da seguinte forma: O primeiro argumento da função é o argumento mais importante, isto é, a entidade principal que precisará ser usada pela função para que ela possa realizar seu objetivo; já os outros são como configurações, especificações que passamos para a função que podem mudar seu comportamento.

Para deixar tudo isso mais claro, vamos modificar o exemplo da função peso(). A nova função poderá receber a aceleração da gravidade tanto como g, quanto como gravidade. Com essas especificações, teríamos o seguinte código para a desejada função:

Exceptions

Até aqui, já falamos sobre diversas estruturas de dados, funções nativas importantes, como criar funções, como criar loops entre outras coisas. Agora, vamos falar das Exceptions. Imagine que você tem uma função que soma dois números, mas você passa como argumentos um inteiro e um texto. Isso acarretará num erro, uma Exception. Mais especificamente, receberemos um erro deste tipo:

TypeError: unsupported operand type(s) for +: 'int' and 'str'

Uma Exception leva a interrupção da execução do código: o programa será terminado. A exceção acima é do tipo TypeError, que indica que as variáveis utilizadas têm tipo errado. Existem vários outros tipos de exceções, como ValueError, que indica que algum argumento da função tinha um valor inválido.

Porém, podemos tratar essas exceções, de modo que quando ocorrer o erro, o comportamento do programa seja diferente. Por exemplo, poderíamos fazer com que, ao invés do programa retornar o erro acima, retorne a seguinte mensagem:

Por favor, digite dois números!

Por outro lado, podemos criar Exceptions, ou seja, podemos fazer com que o programa termine com um erro.

Para exemplificar como brincar com as Exceptions, utilizaremos o exemplo do programa que calcula a distância entre p0 e uma série de pontos, copiado abaixo para facilitar a consulta:

Queremos garantir algumas condições para o funcionamento da função:

  • Deve-se ter, no mínimo, um ponto além de p0 (caso contrário, deve ser criada uma Exception de tipo ValueError).
  • Um ponto deve ser representando por uma lista de, pelo menos, dois elementos (caso existam mais do que 2, os outros serão ignorados).
  • Os dois elementos da lista devem ser numéricos: int ou float (caso contrário, deve ser printado Por favor, digite dois números!).

A fim de satisfazer essas condições, nosso código fica:

Aplicações

Para te incentivar a correr atrás de mais conhecimento, listarei aqui algumas coisas que é possível fazer com Python:

  • Web Scraping: É possível utilizar Python para criar Crawlers e robôs para extrair dados automaticamente de sites da internet. Dê uma olhada nestas bibliotecas: Scrapy e BeautifulSoup.
  • Command line interface programs: Pode-se utilizar Python para criar scripts que são rodados por linha de comando, sendo possível utilizar argumentos. É extremamente útil para automatizar processos. Procure por: ArgParse e Click.
  • Applications, APIs: Existem frameworks que permitem que seja possível criar APIs e aplicações com Python. Leia um pouco sobre: Flask e Django.
  • Data Pipelines: Existem bibliotecas que permitem que você encadeie Tasks e processos para criar uma Pipeline de Dados complexa e robusta para realizar ETLs, processamentos e execução de modelos. Procure: Luigi e Airflow.
  • Modelagem, Programação Científica, Data Science, Visualização e Machine Learning: O Python tem sido muito usado para modelagem estatística, programação científica, Data Science, Visualização de Dados e Machine Learning, como você já deve ter ouvido falar. É possível, com certa facilidade, criar algoritmos complexos de predição, classificação etc. Dê uma boa lida sobre: Pandas, Numpy, Scikit-learn, Matplotlib, Keras e Tensorflow.

E agora?

Agora que já vimos o básico de Python, podemos usar bibliotecas como as listadas acima (pandas, numpy, …) para entender melhor como funciona a ciência de dados e o aprendizado de máquina. A partir da próxima semana, começaremos a direcionar nosso foco nessa direção. Se quiser saber mais, siga a nossa página no Facebook e fique ligado nos posts.

--

--