Missão

Desenvolvermos soluções acessíveis e de qualidade, solucionando os problemas e agregando valor ao serviço prestado por nossos clientes.

Visão

Sermos reconhecidos como profissionais de excelência em nossas áreas de atuação.

Compromisso

Fornecer aos clientes o melhor serviço e com a melhor qualidade.

Instant Hacking

Esta é uma pequena introdução à arte de programação, com exemplos escritos na linguagem de programação Python. (Se você já sabe como programar mas deseja uma pequena introdução ao Python, pode querer olhar meu artigo Instant Python.)

Esta não é uma página a respeito de invasão de computadores ou sistemas de terceiros. Eu não estou ligado a este tipo de atitude, portanto não enviem-me mensagens a este respeito. Para maiores informações sobre o que é realmente ser um hacker consulte hackerethic.org.

Nota: Para que os exemplos funcionem adequadamente digite-os em um arquivo e só então execute-os com o interpretador; não tente executá-los diretamente a partir do interpretador interativo - nem todos os exemplos funcionarão. (Por favor, não pergunte-me por detalhes quanto a isto. Cheque a documentação ou envie um email para help@python.org).

O ambiente

Para programar em python você deve ter o interpretador instalado. Ele está disponível para a maioria das plataformas (incluindo Macintosh, Unix e Windows). Maiores informações podem ser obtidas no web site do Python. Você também deve ter um editor de textos (como o Emacs, bloco de notas ou semelhante).

O que é Programação?

Programar um computador é dar-lhe um conjunto de instruções que dizem o que deve ser feito. Um programa de computador assemelha-se a receitas de culinária de diversas maneiras. Por exemplo [1]:

Salada SPAM Fiesta

Ingredientes:

Marinado:
 1/4 xícara de suco de lima
 1/4 xícara de molho de soja com baixa quantidade de sódio
 1/4 xícara de água
 1 colher de sopa de óleo vegetal
 3/4 colher de chá de cominho
 1/2 colher de chá de orégano
 1/4 colher de chá de molho de pimenta picante
 2 dentes de alho, amassados

Salada:
 1 (340 g) lata de carne SPAM com pouco sódio, fatiada
 1 cebola, fatiada
 1 pimentão, cortado em fatias
 Alface
 12 tomatinhos, cortados em metades

Instruções:

 Numa jarra com tampa, combine todos os ingredientes do marinado;
 agite bem. Coloque as fatias da carne em um saco plástico. Molhe-a
 com o marinado. Sele o plástico; deixe marinando por 30 minutos na
 geladeira. Remova a carne do saco; separe 2 colheres de sopa de
 marinado. Aqueça o marinado separado em uma panela grande. Adicione a
 carne, as cebolas e a pimenta verde. Cozinhe de 3 a 4 minutos ou até
 que a carne esteja aquecida. Separe 4 porções individuais de salada
 de alface. Despeje a mistura quente da salada sobre a alface. Faça a
 guarnição com metades de tomates. Serve 4 pessoas.
NOTA DO TRADUTOR: Para informações sobre o 'SPAM' aqui citado visite o site http://www.spam.com

Claro, nenhum computador entenderá isto... E a maioria não seria capaz de fazer uma salada mesmo se compreendessem a receita. Então, o que temos que fazer para tornar esta receita mais amigável para o computador? Bem, basicamente duas coisas. Temos que (1) expressá-la de uma maneira que o computador possa entender, e (2) falar de coisas que ele possa manipular para obter algo.

O primeiro ponto indica que teremos que usar uma linguagem - uma linguagem de programação para a qual temos um programa interpretador, e o segundo ponto indica que não podemos experar que o computador faça uma salada - mas podemos esperar que ele faça somas, escreva mensagens na tela, etc.

Olá...

Eis uma tradição em tutoriais de linguagens de programação: eles sempre começam com um programa que mostre a mensagem "Olá mundo!" na tela. Em Python esta é uma tarefa bem simples:

print "Olá mundo!"

Este programa é basicamente como a receita acima (embora seja bem mais curta!). Ele informa ao computador o que fazer: mostrar (print) "Olá mundo!". Muito mais fácil que tirar doce de criança. E se quiséssemos que ele fizesse mais coisas?

print "Olá mundo!"
print "Adeus mundo!"

Não foi nada difícil, foi? E também não foi muito interessante. Desejamos fazer algo com os ingredientes assim como fizemos na salada. Mas que ingredientes temos? Primeiro temos cadeias de texto (strings) como a "Olá mundo!", mas também temos números. Digamos que queremos que o computador calcule a área de um retângulo para nós. Poderíamos fornecer-lhe a seguinte receita:

# A área de um retângulo

# Ingredientes:

largura = 20
altura = 30

# Instruções:

area = largura * altura
print area

Você provavelmente já notou a semelhança (mesmo que pouca) com a receita da salada. Mas como isto funciona? Primeiro, todas as linhas iniciadas por # são denominadas comentários e são ignoradas pelo computador. Por outro lado, inserir pequenas explicações como estas pode ser importante para tornar o seu programa mais legível para seres humanos.

Agora as linhas que parecem com foo = bar são chamadas atribuições (assignments). No caso largura = 20 informamos ao computador que a largura deve ser 20 a partir de agora. O que significa que "a largura é 20"? Significa que uma variável com o nome largura foi criada (ou se ela já existia, foi reutilizada) e recebeu o valor 20. Então, quando usarmos a variável mais tarde, o computador saberá seu valor. Portanto,

largura * altura

é essencialmente igual a

20*30

que é calculado como 600, que é então atribuído à variável com o nome area. A instrução final é de que o programa deve exibir o valor da variável area de modo que o que você vê ao executar este programa é simplesmente

600
Nota: Em algumas linguagens é necessário informar ao computador quais variáveis serão usadas logo no início do programa (como os ingredientes da salada). O Python é esperto o suficiente para descobri-las conforme o programa é analisado.

Feedback

Certo. Agora você consegue realizar cálculos simples e até mesmo alguns mais avançados. Por exemplo, você pode querer que um programa calcule a área de uma circunferência ao invés de um retângulo:

raio = 30

print raio * raio * 3.14

Entretanto, este programa não é significativamente mais interessante que o programa do retângulo. Pelo menos em minha opinião. Ele é um tanto quanto inflexível. E se o círculo que desejássemos tivesse um raio de 31 unidades? Como o computador saberia? É mais ou menos como a parte da receita da salada que diz: "Cozinhe por 3 ou 4 minutos ou até que a carne esteja aquecida." Para saber quando ele está cozido, nós checamos. Precisamos de respostas, feedback às nossas solicitações ou então uma entrada de dados (input). Como o computador saberá o raio de nossa circunferência? Ele também precisa de informações, dados... O que podemos fazer é checar o raio:

raio = input("Qual é o raio?")

print raio * raio * 3.14

Agora as coisas estão ficando quentes... input é o que chamamos de função. (Você aprenderá a criar suas próprias funções em alguns momentos. A função input é o que chamamos de função interna à linguagem, ou seja, ela existe diretamente no interpretador Python.) Simplesmente dizendo

input

não fará muita coisa... Você precisa de um par de parênteses no final desta instrução. Então, input() funcionaria - esta instrução simplesmente esperaria pelo usuário digitar o raio. A versão anterior é um pouco mais amigável para o usuário pois mostra uma mensagem informando o que ele deve fazer. Quando colocamos algo como a pergunta "Qual é o raio?" entre os parênteses de uma chamada a uma função damos o nome de passagem de parâmetros para a função. A coisa (ou coisas) nos parênteses é (ou são) o(s) parâmetro(s). Neste caso passamos uma pergunta como um parâmetro de modo que a função input saiba o que mostrar antes de solicitar a resposta do usuário.

Mas como a resposta chega à variável raio? A função input, quando chamada - ou invocada -, retorna um valor (como muitas outras funções). Você não tem que usar est valor, mas no nosso caso queremos utilizá-lo. Então, as duas instruções a seguir têm significados completamente diferentes:

foo = input

bar = input()

foo agora contém a própria função input (e pode ser usada exatamente como ela, na forma foo("Qual sua idade?"); isto é conhecido como chamada dinâmica a uma função) enquanto bar contém o que for digitado pelo usuário.

Fluxo

Agora podemos escrever programas que desempenhem ações simples (aritmética e impressão na tela) e podemos receber dados de entrada do usuário. Isto é útil, mas ainda estamos limitados à tão famosa execução seqüencial de comandos, isto é - eles têm que ser executados em uma ordem fixa. A maioria da receita da sala é seqüencial ou linear também. Mas e se quiséssemos dizer ao computador como verificar o cozido? Se ele estiver aquecido, então deve ser removido do forno - caso contrário, deve ser cozido por mais um minuto aproximadamente. Como informamos isto?

O que queremos fazer é controlar o fluxo do programa. Ele pode ir em duas direções - retirar a carne, ou deixá-la no forno. Podemos escolher e a condição é se ela está ou não propriamente aquecida. Isto é chamado de execução condicional. Podemos implementar isto da seguinte maneira:

temperatura = input("Qual a temperatura do cozido?")

if temperatura > 50:
   print "A salada está cozida apropriadamente."
else:
   print "Cozinhe um pouco mais."

O significado disto deve ser óbvio: se (if) a temperatura for maior que 50 graus centígrados, então mostre a mensagem informando ao usuário que a salada está cozida apropriadamente, senão diga ao usuário para cozinha a salada um pouco mais.

Nota: A indentação - o espaço dado no início da linha - é importante no Python. Blocos e condicionais devem ser indentados (e indentados de maneira uniforme; geralmente um <TAB> conta como 8 espaços) de maneira que o interpretador saiba dizer onde eles começam e terminam. Isto também torna o programa mais legível para os seres humanos.

Voltemos aos nossos cálculos de áreas. Você consegue ver o que este programa faz?

# Programa para cálculo de áreas

print "Bem-vindo ao programa de cálculo de áreas"
print "-----------------------------------------"
print

# Mostre o menu
print "Por favor, selecione uma forma:"
print "1  Retângulo"
print "2  Circunferência"

# Obtenha a escolha do usuário
forma = input("> ")

# Calcule a área:
if forma == 1:
   altura = input("Por favor, entre com a altura: ")
   largura = input("Por favor, entre com a largura: ")
   area = altura * largura
   print "A área é", area
else:
   raio = input("Por favor, entre com o raio: ")
   area = 3.14*(raio**2)
   print "A área é", area

Novas coisas neste exemplo:

  1. A instrução print usada sem parâmetros exibe uma linha em branco
  2. == checa se duas coisas são iguais, oponde-se ao = que atribui o valor do lado direto à variável do lado esquerdo. Esta é uma distinção importantíssima!
  3. ** é o operador de potenciação do Python - portanto o quadrado do raio é escrito como raio**2
  4. O print pode imprimir mais de uma coisa. Apenas separe-as com vírgulas. (Elas serão separadas por um espaço na hora da exibição.)

O programa é bem simples: ele pede um número, que informa se o usuário deseja calcular a área de um retângulo ou uma circunferência. Então, ele usa uma instrução if (execução condicional) para decidir qual bloco deverá usar para o cálculo da área. Estes dois blocos são, em sua essência, os mesmo que foram usados nos exemplos anteriores para o cálculo de áreas. Note como os comentários tornam o código mais legível. É dito que o primeiro mandamento da programação é: "Farás comentários!" De qualquer maneira, este é um ótimo hábito para se adquirir.

Exercício

Melhore o programa acima para incluir cálculos de áreas de quadrados, onde o usuário entre o tamanho de um dos lados. Há apenas uma coisa que você precisa saber para isso: se você tem mais de duas escolhes pode escrever algo como:

if foo == 1:
   # Faça algo...
elif foo == 2:
   # Faça outra coisa...
elif foo == 3:
   # Faça algo completamente diferente... 
else:
   # Quando tudo mais falha... 

Aqui elif é um código misterioso que significa "senão se" (else if) :). Portanto, se foo for um, faça algo; entretanto se foo for dois, faça outra coisa, etc. Você pode querer adicionar outras opções paara o programa - como triângulos ou polígonos arbitrários. Você é quem decide.

Loops

A execução sequencial e os condicionais são apenas duas das três principais maneiras de se programar. A terceira é o loop. Na seção anterior eu propus uma solução para checar se a carne estava cozida, mas ela era claramente inadequada. O que aconteceria se a carne não estivesse pronta na nossa próxima checagem? Como saberíamos quantas vezes precisaríamos checá-la? A verdade é que nunca poderíamos saber. E não deveríamos ter que saber. Devemos ser capazes de pedir ao computador para que ele fique checando até a carne ficar pronta. Como fazemos isso? Você adivinhou - usamos loops ou execuções repetidas.

O Python tem dois tipos de loop: loops while e loops for. Loops for talvez sejam os mais simples. Por exemplo:

for comida in "carne", "ovos", "tomates":
    print "Adoro", comida

Isto significa: para cada elemento na lista "carne", "ovos", "tomates", mostre que você os adora. O bloco no interior do loop é executado uma vez para cada elemento, e a cada vez, o elemento atual é associado à variável comida (neste caso). Outro exemplo:

for numero in range(1,100):
    print "Olá mundo!"
    print "Faltam apenas", 100 - number, "vezes..."

print "Olá mundo!"
print "Esta foi a última... Ufa!"

A função range retorna uma lista de números no intervalo dado (incluindo o primeiro e excluindo o último... Neste caso, [1..99)). Então, parafraseando isto:

O conteúdo do loop é executado para cada número no intervalo de números de (e inclusive) 1 até (e exclusive) 100. (O que o corpo do loop e as instruções fazem é deixado como um exercício.)

Mas isto ainda não nos ajuda com nosso problema na cozinha. Se quiséssemos checar a carne uma centena de vezes, então esta seria uma solução insteressante; mas não sabemos se será o suficiente - ou se será muito. Apensas desejamos manter a checagem enquanto a carne ainda não está quente o suficiente (ou até que ela esteja quente o suficiente - uma questão de ponto de vista). Para isto usamos o while:

# Programa para cozimento de carne

# Obtenha a função sleep
from time import sleep

print "Por favor, inicie o cozimento. (Voltarei em 3 minutos.)"

# Aguarde por 3 minutos (isto é, 3 * 60 segundos)...
sleep(180)

print "Volteeeeeiii! :)"

# Quão quente é o suficiente?
quente_suficiente = 50

temperatura = input("Quão quente está a carne? ")
while temperatura < quente_suficiente:
      print "Não está quente o suficiente... Cozinhe um pouco mais..."
      sleep(30)
      temperatura = input("Certo. Como ela está agora? ")

print "Está quente o suficiente - Está pronto!"

Novas coisas neste exemplo...

  1. Algumas funções úteis estão armazenadas em módulos e podem ser importadas. Neste caso importamos a função sleep (que faz com que o programa fique em pausa por um dado número de segundos) do módulo time que vem com o Python. (É possível você criar seus próprios módulos também...)

Exercício 1

Escreva um programa que leia continuamente números digitados pelo usuário e some-os até que o resultado atinja 100. Escreva outro programa que leia 100 números digitados pelo usuário e imprima sua soma.

Programas maiores - Abstração

Se você deseja uma rápida noção do conteúdo de um livro você não o folheia em todas as páginas - você olha o índice, certo? Ele simplesmente apresenta uma listagem dos principais tópicos do livro. Agora imagine-se escrevendo um livro de receitas. Muitas das receitas, como "Spam cremoso e macarrão" e "Torta suíça de spam" podem conter coisas parecidas, como o spam, neste caso - ainda que você não queria repetir a receita de como preparar o spam em cada receita. (Certo... Você não cozinha spam... Mas acompanhe-me, só para que o exemplo funcione :)). Você colocaria a receita para o spam em um capítulo separado e simplesmente o referencia nas outras receitas. Então, ao invés de escrever toda a receita cada uma das vezes, você apenas usaria o nome do capítulo. Em um programa de computador isto é chamado abstração.

Já passamos por algo assim? Sim! Ao invés de dizer ao computador exatamente como obter uma resposta do usuário (Certo, não poderíamos realmente fazer isto... mas não poderíamos fazer o spam também, então... :)) nós simplesmente usamos input - uma função. Podemos criar nossas próprias funções para usar este tipo de abstração.

Digamos que desejamos encontrar o maior inteiro que é menor que um número positivo qualquer. Por exemplo, para o número 2,7 este número seria 2. Isto é chamado de "piso" de um número. (Isto poderia ser feito automaticamente com a função interna do Python int mas, novamente, a intenção é apenas dar exemplos...) Como faríamos isto? Uma solução simples seria tentar todas as possibilidades a partir de zero:

numero = input("Qual o número? ")

piso = 0
while piso < numero:
      piso = piso+1

piso = piso-1

print "O piso de", number, "é", piso

Perceba que o loop encerra-se quando piso não é mais menor que numero; adicionamos uma unidade a mais a piso, portanto devemos subtraí-la posteriormente. O que aconteceria se quiséssemos usar este recurso em uma expressão matemática complexa? Teríamos que escrever o loop inteiro para cada número que precisássemos calcular. Nada agradável... Você provavelmente já adivinhou o que faremos: colocaremos tudo isto em uma função criada por nós mesmos e denominada "piso":

def piso(numero):
    resultado = 0
    while resultado < numero:
          resultado = resultado+1
    resultado = resultado-1
    return resultado

Novas coisas neste exemplo...

  1. Funções são definidas com a palavra-chave def seguida pelo nome da mesma e com os parâmetros esperados entre parênteses.
  2. Se a função deve retornar algum valor, isto deve ser feito com a palavra-chave return (que automaticamente termina a função).

Agora que já definimos a função, podemos utilizá-la:

x = 2.7
y = piso(2.7)

Após isto, y deve ter o valor 2. Também é possível criar funções com mais de um parâmetro:

def soma(x,y):
    return x+y

Exercício 2

Escreva uma função que implemente o método de Euclides para encontrar um fator comum de dois números.

O método consiste no seguinte:

  1. Você tem dois números, a e b, onde a é maior que b
  2. Você repete o seguinte até que b seja zero:
    1. a é mudado para o valor de b
    2. b é mudado para o resto de a (o original, antes da mudança) dividido por b (também antes da mudança)
  3. Você então retorna o último valor de a

Dicas:

Mais a respeito de funções

Como foi o exercício? Foi difícil? Ainda está um pouco confuso com funções? Não se preocupe - ainda não mudamos de assunto.

O tipo de abstração que temos usado quando construímos funções é chamado de abstração procedural, e muitas linguagens usam a palavra procedure (inglês para procedimento) juntamente com a palavra function (inglês para função). Na verdade os dois conceitos são diferentes, mas ambos são chamados funções no Python (já que são definidos e usados do mesmo modo, aproximadamente).

Qual a diferença (em outras linguagens) entre funções e procedimentos? Bem, como você viu na seção anterior, funções podem retornar valores. A diferença reside no fato de que procedimentos não retornam valores. De diversas maneiras esta divisão de funções em dois tipos - as que retornam e as que não retornam valores - pode ser bastante útil.

Uma função que não retorna um valor (um procedimento) é usado como um "sub-programa" ou uma subrotina. Invocamos a função e o programa realiza algumas ações, como fazer creme ou qualquer coisa. Podemos, então, usar esta função em muitos lugares sem termos que reescrever o código. (Isto é chamado de reutilização de código - falarei mais a respeito disso depois.)

A utilidade de tal função (ou procedimento) reside em seus efeitos colaterais - ela muda seu ambiente (misturando o açúcar e o creme e batendo-os, por exemplo...) Vejamos um exemplo:

def ola(quem):
    print "Olá ", quem

ola("mundo")
    # Mostra "Olá mundo"

Mostrar coisas é considerado um efeito colateral e, como isto é tudo o que esta função faz, é bem típico para um procedimento. Mas... Ele realmente não muda o ambiente, muda? Como um procedimento poderia fazer isso? Vamos tentar:

# A maneira *errada* de fazê-lo
idade = 0

def ajustaIdade(a):
    idade = a

ajustaIdade(100)
print idade
# Mostra "0"

O que há de errado aqui? O problema é que a função ajustaIdade cria suas próprias variáveis locais, dentre elas uma com o mesmo nome idade. Como poderíamos evitar isto? Podemos usar algo chamado de variáveis globais.

Nota: Variáveis globais não são muito utilizadas em Python. Elas facilmente levam a uma má estrutura, ou algo conhecido como código macarrônico. Eu as uso aqui apenas para introduzir técnicas mais complexas - por favor, evite-as se possível.

Informando ao interpretador que uma variável é global (feito com um comando parecido com global idade) nós efetivamente informamos que ele deve usar a variável de fora da função ao invés de criar uma nova localmente. (Então, temos global em oposição a local.) O programa pode, então, ser reescrito da seguinte maneira:

# A maneira correta, mas não-tão-boa de fazer isto
idade = 0

def ajustaIdade(a):
    global idade
    idade = a

ajustaIdade(100)
print idade
# Mostra "100"

Quando você aprender a respeito de objetos (abaixo), você verá que uma maneira mais apropriada de fazer esta operação será usando objetos com uma propriedade idade e um método ajustaIdade. Na seção de estruturas de dados você verá alguns exemplos melhores de funções que modificam seu ambiente.

Bem, que tal algumas funções reais, então? O que é, realmente, uma função? Funções matemáticas são uma espécie de "máquina" que recebem dados de entrada e calculam um resultado. Ela retornará o mesmo resultado o tempo todo, desde que receba os mesmos dados. Por exemplo:

def quadrado(x):
    return x*x

Esta é a mesma função que a função matemática f(x)=x². Comporta-se como uma boa função, ou seja, depende apenas da entrada e não modifica o ambiente de nenhuma maneira.

Então, após ter mostrado duas maneiras de se fazer funções: um tipo é mais um procedimento e não retorna um valor, o outro é como uma função matemática e não faz nada além de retornar um valor (quase sempre). Claro que há a possibilidade de criar algo entre estes dois extremos embora quando uma função mude coisas isto deva ficar bem claro. Você pode informar isto através do nome da função, por exemplo, através do uso de um substantivo para funções "puras" como quadrado e um imperativo para funções semelhantes a procedimentos, como ajustaIdade.

Mais ingredientes - estruturas de dados

Você já conhece muita coisa: como obter um dado de entrada e fornecer uma saída, como estruturar algoritmos complicados (programas) e realizar operações aritméticas; e o melhor ainda está por vir.

Quais ingredientes temos usado em nossos programas até agora? Números e cadeias de texto. Certo? Meio chato... Não, vamos introduzir um conjunto de outros ingredientes que tornarão as coisas um pouco mais excitantes.

Estruturas de dados são ingredientes que estruturam dados. (Supresa!) Um simples número não possui realmente muita estrutura, possui? Mas vamos dizer que queremos mais números adicionados a um único ingrediente - isto teria alguma estrutura. Por exemplo, podemos querer uma lista de números. Isto é fácil:

[3,6,78,93]

Eu mencionei listas na seção sobre loops, mas não havia dito muito a respeito delas. Agora você já sabe como criá-las. Apenas liste os elementos separando-os por vírgulas e colocando-os entre colchetes.

Vamos pular para um exemplo que calcula números primos (números divisíveis apenas por si próprios e por 1)>

# Calcula todos os números primos abaixo de 1000
# (Esta não é a melhor maneira de se fazer isto, mas...)

resultado = []
candidatos = range(3,1000)
base = 2
produto = base

while candidatos:
    while produto < 1000:
        if produto in candidatos:
           candidatos.remove(produto)
        produto = produto + base

    resultado.append(base)
    base = candidatos[0]
    produto = base
    del candidatos[0]

resultado.append(base)
print resultado

Coisas novas neste exemplo...

  1. A função interna range retorna uma lista que pode ser utilizada como todas as outras listas. (Ela inclui o primeiro índice, mas não o último.)
  2. Uma lista pode ser usada como uma variável lógica. Se ela não estiver vazia, então é verdadeira - se estiver vazia, então é falsa. Portanto, a instrução while candidatos significa "enquanto a lista de nome candidatos não estiver vazia" ou simplesmente "enquanto ainda houverem candidatos".
  3. Você pode escrever if algumElemento in algumaLista para checar se o elemente é parte da lista
  4. Você pode escrever algumaLista.remove(algumElemento) para remover algumElemento de algumaLista.
  5. Você pode adicionar uma lista ao final de outra usando algumaLista.append(outraLista). Na verdade, você também pode usar o operador + (como em algumaLista = algumaLista + outraLista) mas isto não é tão eficiente.
  6. Você pode obter os elementos de uma lista fornecendo suas posições como um número (onde o primeiro elemento, estranhamento, é o elemento 0) entre colchetes após o nome da lista. Então, algumaLista[3] é o quarto elemento da lista algumaLista. (Mais sobre isto a seguir.)
  7. Você pode remover variáveis usando a palavra-chave del. Ela também pode ser usada (como no exemplo) para remover elementos de uma lista. Portanto, del algumaLista[0] remove o primeiro elemento de algumaLista. Se a lista fosse [1, 2, 3] antes da remoção, ela seria [2, 3] após.

Antes de prosseguirmos para as explicaçõs dos mistérios da indexação de listas, irei explicar brevemente o exemplo.

Esta é uma versão de um antigo algoritmo chamado "A busca de Erastótenes" (ou algo próximo a isto). Ele considera um conjunto (ou, neste caso, uma lista) de números candidatos e então sistematicamente remove os números que sabe-se não serem primos. Como sabemos? Porque eles são produtos de dois outros números.

Começamos com uma lista de candidatos contendo os números [2 .. 999] - sabemos que 1 é primo (na verdade, pode ou não ser, dependendo de para quem você perguntar), e nós desejamos todos os primos abaixo de 1000. (Nossa lista de candidatos é, realmente, de [3 .. 999], mas 2 também é um candidato já que se trata de nossa primeira base). Também temos uma lista chamada resultado que contém todos os resultados atualizados até o momento. Para começar, esta lista contém apenas o número 1. Também temos uma variável chamada base. Para cada iteração ("turno") do algoritmo, removemos todos os números que são múltiplos desta base (que é sempre o menor de todos os candidatos). Após cada iteração sabemos que o menor número restante é primo (já que todos os números que eram produtos dos menos foram removidos - entendeu?). Portanto, adicionamos este número a resultado, mudamos a nova base para este número e removemo-lo da lista candidatos (de maneira que não o processemos novamente). Quando a lista candidatos estiver vazia, a lista resultado conterá todos os números primos. Inteligente, não?

Coisas para se pensar a respeito: O que há de especial com a primeira iteração? Aqui a base é 2 e mesmo assim ela também é removida da "busca"? Por que? Por que isto não acontece com as demais bases? Podemos ter certeza de que produto está sempre na lista candidatos quando desejamos removê-lo? Por que?

Agora, o que temos? Ah, sim! Indexação. E partições. Estas são as maneiras de se obter elementos individuais a partir de listas no Python. Você já viu indexações simples em ação. É bem básica. Eu, na verdade, já lhe disse tudo o que você precisa saber a respeito dela, exceto por uma coisa: índices negativos contam a partir do final da lista. Então, algumaLista[-1] é o último elemento de algumaLista, algumaLista[-2] é o penúltimo e assim por diante.

Partições, entretanto, devem ser-lhe novas. São similares à indexação, exceto que com o particionamento você pode obter uma parte inteira da lista, e não apenas um único elemento. Como funciona? Assim:

comida = ["carne","carne","ovos","salsichas","carne"]

print comida[2:4]
# mostra "['ovos', 'salsichas']"

Mais abstração - Objetos e Programação Orientada a Objetos

Eis um termos propagandístico: "Programação orientada a objetos."

Como o título desta seção sugere, programação orientada a objetos é apenas mais uma maneira de abstrair detalhes. Procedimentos abstraem comandos simples em operações mais complexas através de uma atribuição de um nome a eles. Na OOP (programação orientada a objetos) não tratamos as operações desta maneira, mas como objetos. (Vai querer me dizer que isto não foi supreendente, hein?) Por exemplo, se estivéssemos fazendo o programa-de-cozimento-de-carne, ao invés de escrevermos diversos procedimentos que lidam com a temperatura, o tempo, os ingredientes, etc. criaríamos um objeto cozido. Ou, talvez, poderíamos ter um objeto forno e um objeto relógio também... Agora, coisas como temperatura seriam atributos apenas do objeto cozido, enquanto que o tempo seria lido do objeto relógio. E para fazer com que nosso programa faça algo, poderíamos ensinar-lhe alguns métodos de objetos; por exemplo, o forno poderia saber como cozinhar a carne, etc.

Então, como fazemos isto em Python? Bem, não podemos criar um objeto diretamente. Ao invés de apenas criarmos um forno, precisamos de uma receita descrevendo como são os fornos. Esta receita, então, descreve uma classe de objetos que conhecemos por fornos. Uma classe bem simples poderia ser:

class Forno:
   def inserirCozido(self, cozido):
       self.cozido = cozido

   def obterCozido(self):
       return self.cozido

Bem estranho, não?

Coisas novas neste exemplo...

  1. Classes de objetos são definidas através da palavra-chave class.
  2. Nomes de classes geralmente começam com uma letra maiúsculas, enquanto que funções e variáveis (assim como nomes de métodos e atributos) começam com letras minúsculas.
  3. Métodos (isto é, as funções ou operações que os objetos sabem realizar) são definidos normalmente, mas dentro do bloco class.
  4. Todos os métodos de objetos devem possuir um primeiro parâmetro chamado self (ou algo parecido...) A razão tornar-se-á (espero) clara em um momento.
  5. Atributos e métodos de um objeto são acessados da seguinte maneira: meuCozido.temperatura = 2 ou dilbert.seja_legal().

Eu diria que algumas coisas ainda não estão claras a respeito do exemplo. Uma delas seria o que é essa coisa de self? E, agora que temos uma receita de objeto (isto é, uma classe), como criamos um objeto?

Comecemos pelo último ponto. Um objeto é criado invocando-se sua classe como se fosse uma função:

meuForno = Forno()

meuForno agora contém um objeto Forno e é chamado comumente de instância da classe Forno. Vamos admitir que você criou uma classe Cozido também; então poderíamos dizer algo como:

meuCozido = Cozido()
meuForno.inserirCozido(meuCozido)

meuForno.cozido agora conteria meuCozido. Por quê? Porque, quando invocamos um dos métodos de um objeto o primeiro parâmetro, geralmente nomeado self sempre contém o próprio objeto. (Inteligente, não?) Portanto, a linha self.cozido = cozido ajusta o atributo cozido do atual objeto Forno para o valor do parâmetro cozido. Note que estas são duas coisas diferentes, mesmo ambas sendo chamadas cozido neste exemplo.

Resposta ao exercício 2

Eis uma versão bem concisa do algoritmo:

def euclid(a,b):
    while b:
          a,b = b,a % b
    return a

Referências

[1] Receita para a Salada Spam Fiesta obtida do livro digitar "Hormel Foods Digital Recipe Book".

Informa

“Um novo conceito em prestação de serviços”