'''por:''' Magnus Lie Hetland<
> '''tradução:''' WanderleiAntonioCavassin
<>
Este é um curso intensivo mínimo para a linguagem de programação [[http://www.python.org/doc/Introduction.html|Python]]. Para aprender mais, veja a documentação no site [[http://www.python.org|www.python.org]]; especialmente o [[http://www.python.org/doc/tut|tutorial]]. Se você está se perguntando porque deveria se interessar, veja esta [[http://www.python.org/doc/Comparisons.html|comparação]] entre o Python e outras linguagens.
Esta introdução tem recebido [[http://www.idi.ntnu.no/~mlh/python/praise.html|elogios]] de leitores satisfeitos, e está sendo traduzida para vários idiomas, entre os quais russo, norueguês, português (esta página!) e espanhol. A versão original, em inglês, está [[http://www.idi.ntnu.no/~mlh/python/different.html|aqui]].
= O básico =
Para começar, pense em Python como sendo pseudo-código. Isto é quase uma verdade. Variáveis não têm tipos, assim você não precisa declará-las. Elas são criadas quando você lhes atribui um valor, e são destruídas quando não forem mais usadas. A atribuição é feita pelo operador =. A igualdade é testada com o operador ==. Você pode atribuir mais de uma variável ao mesmo tempo:
{{{
#!python
x,y,z = 1,2,3
}}}
. primeiro, segundo, terceiro = primeiro, segundo, terceiro
ou
um, dois, tres = 1, 2, 3{{{
#!python
a = b = 123
}}}
Os blocos são indicados somente pela indentação (nada de BEGIN/END ou chaves). Algumas estruturas de controle são:
{{{
#!python
if x < 5 or (x > 10 and x < 20):
print "O valor está correto."
if x < 5 or 10 < x < 20:
print "O valor está correto."
for i in [1,2,3,4,5]:
print "Esta é a iteração número", i
x = 10
while x >= 0:
print "x ainda não é negativo."
x = x - 1
}}}
Os primeiros dois exemplos são equivalentes.
A variável de índice no laço {{{for}}} varia de acordo com os elementos de uma lista (escrita como no exemplo). Para fazer um laço for comum (isto é, um laço de contagem), use a função embutida {{{range()}}}.
{{{
#!python
# Mostra os valores de 0 a 99 inclusive.
for valor in range(100):
print valor
}}}
(A linha começando por "#" é um comentário, sendo ignorada pelo interpretador.)
Vejamos: agora você já sabe o suficiente (em teoria) para implementar qualquer algoritmo em Python. Vamos incluir alguma interação básica com o usuário. Para obter dados do usuário (a partir de um ''prompt'' texto), use a função embutida {{{input()}}}.
{{{
#!python
x = input("Por favor digite um número: ")
print "O quadrado desse número é", x*x
}}}
A função {{{input()}}} mostra o texto dado (o qual pode ser vazio) e deixa o usuário entrar qualquer valor válido em Python. Neste caso nós estamos esperando um número - se alguma outra coisa (como uma string) for fornecida, o programa poderá falhar. Para evitar isto nós devemos implementar alguma checagem de erro. Eu não vou entrar em detalhes aqui; é suficiente dizer que se você deseja receber o dado do usuário, literalmente como uma string (assim qualquer coisa pode ser fornecida), use a função {{{raw_input()}}}. Se você deseja converter uma ''string'' s para um inteiro, você poderia usar {{{int(s)}}}.
Nota: Se o usuário deseja fornecer uma ''string'' com {{{input()}}}, ele deverá escrever as aspas explicitamente. Em Python, as ''strings'' podem ser delimitadas com aspas simples ou duplas.
Assim, já que temos estruturas de controle, entrada e saída - agora nós precisamos de algumas estruturas de dados. As mais importantes são as listas e os dicionários. As listas são escritas com colchetes, e podem ser (naturalmente) aninhadas:
{{{
#!python
nome = ["Cleese", "John"]
x = [[1,2,3],[y,z],[[[]]]]
}}}
Uma das coisas mais interessantes sobre as listas é que os seus elementos podem ser acessados separadamente ou em grupos, através de indexação e corte em fatias. A indexação é feita (como em muitas outras linguagens) pela colocação do índice entre os colchetes (Note que o primeiro elemento tem índice 0).
{{{
#!python
print nome[1], nome[0] # Mostra "John Cleese"
nome[0] = "Smith"
}}}
O corte em fatias é parecido com a indexação, indicando-se os índices inicial e final separados por dois pontos (":")
{{{
#!python
x = ["spam","spam","spam","spam","spam","eggs","and","spam"]
print x[5:7] # Mostra a lista ["eggs","and"]
}}}
Observe que o índice final não se inclui no resultado. Se um dos índices é omitido, assume-se que você deseja todos os elementos na direção correspondente. Por exemplo, {{{lista[:3]}}} significa "cada elemento desde o início da lista até o elemento 3, este não incluído." (Poderia-se dizer na verdade que vai até o elemento 4, desde que a contagem inicia do 0... Oh, tudo bem) {{{list[3:]}}} significaria, por outro lado, "cada elemento da lista, começando do elemento 3 (inclusive) até o último inclusive." Para outros resultados bem interessantes, você pode usar números negativos também: {{{list[-3]}}} é o terceiro elemento desde o final da lista...
Já que estamos falando de indexação, é interessante saber que a função embutida {{{len()}}} fornece o tamanho de uma lista (em número de elementos).
E agora, o que há sobre os dicionários? Para ser breve, eles são como listas, mas o seu conteúdo não está ordenado. Como você os indexa então? Bem, cada elemento tem uma chave, ou um "nome" que é usado para buscar o elemento tal qual um dicionário de verdade. Eis dois dicionários como exemplo:
{{{
#!python
{ "Alice" : 23452532, "Boris" : 252336,
"Clarice" : 2352525, "Doris" : 23624643}
pessoa = { 'nome': "Robin", 'sobrenome': "Hood",
'ocupação': "Ladrão" }
}}}
Agora, para obter a ocupação da pessoa, nós usamos a expressão {{{pessoa["ocupação"]}}}. Se nós desejarmos alterar o seu sobrenome, nos poderíamos escrever:
{{{
#!python
pessoa['sobrenome'] = "de Locksley"
}}}
Simples, não? Como as listas, os dicionários podem armazenar outros dicionários. Ou listas, que já conhecemos. E naturalmente listas podem armazenar dicionários também. Desta forma, você pode conseguir estruturas de dados bastante avançadas.
= Funções =
Próximo passo: Abstração. Queremos dar um nome a um pedaço de código, e chamá-lo com um parâmetro. Em outras palavras - nós queremos definir uma função (ou "procedimento"). Isto é fácil. Use a palavra-chave {{{def}}} assim:
{{{
#!python
def quadrado(x):
return x*x
print quadrado(2) # Mostra 4
}}}
Para os que podem entender: Quando você passa um parâmetro à uma função, você vincula o parâmetro ao valor (passado), criando, portanto, uma nova referência. Se você mudar o "conteúdo" deste parâmetro não afetará o original. Funciona como em Java, por exemplo. Vamos dar uma olhada em um exemplo:
{{{
#!python
def mudar(lista_qualquer):
lista_qualquer[1] = 4
x = [1,2,3]
mudar(x)
print x # Mostra [1,4,3]
}}}
Como você pode ver, a lista original é que foi passada, e se a função mudá-la, essas mudanças serão refletidas para o local de onde a função foi chamada. Note, entretanto, o comportamento no seguinte exemplo:
{{{
#!python
def naoMudar(x):
x = 0
y = 1
naoMudar(y)
print y # Mostra 1
}}}
Por que não há mudança agora? Porque nós ''não mudamos o valor''! O valor passado é o número 1 -- nós não podemos mudar um número do mesmo modo que mudamos uma lista. O número 1 é (e sempre será) o número 1. O que nós realmente fizemos foi mudar o conteúdo da variável local (parâmetro x), e isto não afetará o ambiente (fora da função).
Para os que não entenderam: Não se preocupem com isso :)
Python tem muitas coisas "legais" como argumentos com nome e argumentos com valor padrão, podendo manipular um número variável de argumentos para uma função. Para mais informações sobre isto, veja a [[http://www.python.org/doc/tut/defining.html|seção 4.7]] do tutorial de Python.
Se você sabe como usar funções em geral, isto é basicamente o que você precisa saber sobre elas em Python. (Ah, sim... A palavra-chave {{{return}}} termina a execução da função e retorna o valor dado.)
Uma coisa que é útil saber, entretanto, é que as função são valores em Python. Assim se você tem uma função como quadrado, você pode fazer alguma coisa assim:
{{{
#!python
figura = quadrado
figura(2) # Mostra 4
}}}
Para chamar uma função sem argumentos você deve lembrar de escrever {{{func()}}} e não {{{func}}}. A segunda forma, como mostrado, somente retorna a própria função, como um valor. (Isto ocorre com os métodos dos objetos também... Veja abaixo.)
= Objetos e coisas... =
Eu suponho que você saiba como funciona a programação orientada a objetos. (De outra forma, esta seção não faria muito sentido. Sem problemas... Comece a brincar sem os objetos :).) Em Python você define classes com a palavra-chave (surpresa!) {{{class}}}, assim:
{{{
#!python
class Cesta:
# Lembre-se sempre do argumento *self*
def __init__(self,conteudo=None):
self.conteudo = conteudo or []
def adicione(self,elemento):
self.conteudo.append(elemento)
def mostre_me(self):
result = ""
for elemento in self.conteudo:
resultado = resultado + " " + `elemento`
print "Contém: "+resultado
}}}
Coisas novas aqui:
1. Todos os métodos (funções dentro de um objeto) recebem um argumento adicional no início da lista de argumentos, contendo o próprio objeto. (Chamado self neste exemplo, por convenção.)
1. Métodos são chamados assim: {{{objeto.método(arg1, arg2)}}}.
1. Alguns nomes de métodos, como {{{__init__}}} são pré-definidos, e têm significado especial. {{{__init__}}} é o nome do construtor da classe, isto é, esta é a função que é chamada quando você cria uma instância.
1. Alguns argumentos podem ser opcionais e ter um valor padrão (como mencionado acima, na seção sobre funções). Isto é feito escrevendo-se a definição desta forma:
{{{
#!python
def spam(idade=32): # ...
}}}
. Aqui, {{{spam}}} pode ser chamado com um ou zero parâmetros. Se nenhum for usado, então o parâmetro idade terá o valor 32.
5. "Lógica de curto-circuito." Este é um ponto... Veja abaixo.
5. Aspas simples invertidas convertem um objeto para sua representação como string. (Assim se elemento contém o número 1, então `elemento` é o mesmo que "1" sendo 'elemento' uma string literal.)
5. O sinal de adição + é usado também para concatenação de listas, e strings são na verdade listas de caracteres (o que significa que você pode usar indexação e corte em fatias e a função len com strings. Legal, não acha?)
Nenhum método ou variável membro é protegido (nem privado, nem nada parecido) em Python. Encapsulação é na maioria das vezes um estilo de programação. (Se você realmente precisar, existem convenções para nomes de variáveis, que permitem alguma privacidade :)).
E agora, sobre a lógica de curto-circuito...
Todos os valores em Python podem ser usados como valores lógicos. Alguns dos mais "vazios", tais como [], 0, "" e None representam o valor lógico "falso", enquanto o resto dos valores (como [0], 1 ou "Olá Mundo" representam o valor lógico "verdadeiro".
Assim, expressões lógicas como {{{a and b}}} são avaliadas deste modo: Primeiro, verifique se a é verdadeiro. Se não, então simplesmente retorne-o. Se sim, então simplesmente retorne b (o que irá representar o valor lógico da expressão.). A lógica correspondente para {{{a or b}}} é: se a é verdadeiro, então retorne-o, Se não é, então retorne b.
Este mecanismo faz com que {{{and}}} e {{{or}}} se comportem como os operadores booleanos que implementam, mas eles também permitem escrever expressões condicionais muito curiosas. Por exemplo, o código
{{{
#!python
if a:
print a
else:
print b
}}}
Poderia ser substituído por:
{{{
#!python
print a or b
}}}
Na verdade, isto já é alguma coisa do idioma Python, assim é melhor você ir se acostumando. Isto é o que foi feito no método {{{Cesta.__init__}}}. O argumento conteudo tem um valor padrão {{{None}}} (o que é, entre outras coisas, falso). Portanto, para verificar se ele tem um valor, nós poderíamos escrever:
{{{
#!python
if conteudo:
self.conteudo = conteudo
else:
self.conteudo = []
}}}
É claro, agora você sabe como fazer de uma forma melhor. E por que nós não demos o valor padrão [] no começo? Porque da maneira como o Python funciona, isto daria a todas as Cestas a mesma lista vazia como valor padrão. Tão logo uma das listas começasse a ser preenchida, todas as outras teriam os mesmo elementos, e o padrão não seria mais vazio... Para aprender mais sobre isto você deveria ler a documentação e procurar a diferença entre identidade e igualdade.
Outra forma de fazer o anterior é:
{{{
#!python
def __init__(self, conteudo=[]):
self.conteudo = conteudo[:]
}}}
Você pode adivinhar como isto funciona? Ao invés de usar a mesma lista vazia para todos, nós usamos a expressão {{{conteudo[:]}}} para fazer uma cópia (Usamos uma fatia que contém a lista toda.)
Assim, para fazer uma Cesta e usá-la (isto é. para chamar alguns dos seus métodos) nós devemos fazer algo assim:
{{{
#!python
b = Cesta(['maçã','laranja'])
b.adicione("limão")
b.mostre_me()
}}}
Há outros métodos mágicos além do {{{__init__}}}. Um desses métodos é {{{__str__}}} que define como o objeto será conhecido quando for tratado como uma ''string''. Nós poderíamos usar este método ao invés de {{{mostre_me()}}}:
{{{
#!python
def __str__(self):
result = ""
for elemento in self.conteudo:
resultado = resultado + " " + str(elemento)
return "Contém: "+resultado
}}}
Agora, se nós desejamos mostrar a cesta b, nós usaríamos simplesmente:
{{{
#!python
print b
}}}
Legal, não acha?
Subclasses são feitas assim:
{{{
#!python
class CestaSpam(Cesta):
# ...
}}}
Python permite herança múltipla, assim você pode ter várias superclasses entre parênteses, separadas por vírgulas. Classes são instanciadas assim: {{{x = Cesta()}}}. Construtores são implementados, como disse, com a definição de uma função membro especial {{{__init__}}}. Digamos que {{{CestaSpam}}} tem um construtor {{{__init__(self,tipo)}}}. Então você poderia fazer uma cesta spam assim: {{{y = CestaSpam("maças")}}}.
Se você, no construtor de {{{CestaSpam}}} precisar chamar o construtor de uma ou mais superclasses, você poderia chamá-los desta forma: {{{Cesta.__init__(self)}}}. Note que além dos parâmetros comuns, você deve fornecer explicitamente o {{{self}}}, já que a superclasse {{{__init__}}} não sabe qual instância está tratando.
Para saber mais sobre as maravilhas da programação orientada a objeto em Python, veja [[http://www.python.org/doc/current/tut/node11.html|seção 9]] do tutorial de Python.
= Um truque mental de Jedi =
(Esta seção está aqui porque eu acho que ela é muito interessante. Definitivamente esta seção não é necessária para começar a aprender Python.)
Você gosta de exercícios mentais? Então, se você é realmente ousado, você gostará de ver o ensaio do GuidoVanRossum sobre [[http://www.python.org/doc/essays/metaclasses/|metaclasses]]. Se, entretanto, você prefere não explodir sua mente, irá igualmente satisfazer-se com este pequeno truque.
Python usa espaços de nomes dinâmicos (não léxicos). Isto quer dizer que se há uma função como esta:
{{{
#!python
def suco_laranja():
return x*2
}}}
... onde uma variável (neste caso x) não está ligada a um argumento e não é dado um valor dentro da função, Python usará o valor que ela tiver onde e quando a função for chamada. Neste caso:
{{{
#!python
x = 3
y = suco_laranja()
# y agora é 6
x=1
y = suco_laranja()
# y agora é 2
}}}
Normalmente este é o tipo de comportamento esperado (apesar do exemplo ser um pouco rebuscado - raramente acessamos variáveis desta forma.) Entretanto, algumas vezes pode ser útil ter um espaço de nomes estático, ou seja, armazenar alguns valores do ambiente em que a função é criada. A maneira de fazer isto em Python é por meio dos argumentos padrão.
{{{
#!python
x = 4
def suco_maca(x=x):
return x*2
}}}
Aqui, ao argumento x é atribuído o valor padrão que é o mesmo valor da variável x quando a função é definida. Assim, se nenhum valor é fornecido como argumento para a função, ela irá funcionar assim:
{{{
#!python
x = 3
y = suco_maca():
# y agora é 8
x = 1
y = suco_maca():
# y agora é 8
}}}
Assim - o valor de {{{x}}} não é alterado. Se isto era tudo que nós queríamos, poderíamos simplesmente ter escrito
{{{
#!python
def suco_tomate():
x = 4
return x*2
}}}
ou mesmo
{{{
#!python
def suco_cenoura():
return 8
}}}
Entretanto, o ponto é que o valor de {{{x}}} é obtido do ambiente quando a função é definida. O quanto isto é útil? Vejamos um exemplo: uma função composta.
Nós queremos uma função que funcione assim:
{{{
#!python
from math import sin, cos
sincos = componha(sin,cos)
x = sincos(3)
}}}
Onde componha é a função que queremos fazer, e {{{x}}} tem o valor -0.836021861538, que é o mesmo que sin(cos(3)). Agora, como faremos isto?
(Note que nós estamos usando funções como argumentos... Este é o próprio truque.)
Claramente, componha toma duas funções como parâmetros, e retorna uma função que por sua vez recebe um parâmetro. Assim, um esqueleto da solução seria:
{{{
#!python
def componha(fun1, fun2):
def interior(x):
pass # ...
return interior
}}}
Nós poderíamos tentar return fun1(fun2(x)) dentro da da função interior e deixá-lo tal qual. Não, não, não. Isto teria um comportamento muito estranho. Imagine o seguinte cenário:
{{{
#!python
from math import sin, cos
def fun1(x):
return x + " mundo!"
def fun2(x):
return "Olá,"
sincos = componha(sin,cos) # Usando a versão incorreta
x = sincos(3)
}}}
Agora, qual valor x terá? Resposta: "Olá, mundo!". Por que isto? Porque quando é chamada, ela toma o valor de fun1 e fun2 do ambiente, não aqueles de quando foi criada. Para conseguir a solução correta, tudo que teremos que fazer é usar a técnica descrita anteriormente:
{{{
#!python
def componha(fun1, fun2):
def interior(x, fun1=fun1, fun2=fun2):
return fun1(fun2(x))
return interior
}}}
Agora nós só temos que esperar que ninguém forneça mais de um argumento à função resultante, pois isto quebraria os esquemas :). E, a propósito, já que nós não precisamos do nome interior, e esta função contém somente uma expressão, nós podemos usar uma função anônima, usando a palavra-chave lambda:
{{{
#!python
def componha(f1, f2):
return lambda x, f1=f1, f2=f2: f1(f2(x))
}}}
Sucinto, porém claro. Você tem que gostar :)
(E se você não entendeu nada, não se preocupe. Pelo menos eu espero tê-lo convencido que Python é muito mais do que "uma linguagem para scripts"... :-))
= E agora... =
Só umas coisinhas para terminar. A maioria das funções e classes mais úteis são colocadas em módulos, os quais são na verdade arquivos-texto contendo código Python. Você pode importá-los e usá-los em seus programas. Por exemplo, para usar o método split do módulo padrão string, você pode ter estas duas formas:
{{{
#!python
import string
x = string.split(y)
}}}
Ou...
{{{
#!python
from string import split
x = split(y)
}}}
Para mais informações sobre a biblioteca de módulos padrão, de uma olhada em www.python.org/doc/lib. Contém muitos módulos úteis.
Todo o código em um módulo/script se executa quando é importado. Se você quer que o seu programa seja tanto um módulo importável quanto um programa executável, você pode adicionar alguma coisa parecida com isto no final do programa:
{{{
#!python
if __name__ == "__main__":
executar()
}}}
Esta é uma forma mágica de dizer que se este módulo esta sendo executado como um script executável (isto é, que não está sendo importado por outro script), então a função executar deve ser chamada. E é claro, você poderia fazer qualquer coisa após os dois pontos... :)
E para aqueles que desejam fazer um script UN*X executável, escreva isto como primeira linha do arquivo:
{{{
#!python
#!/usr/bin/env python
}}}
Finalmente, uma breve menção de um conceito importante: Exceções. Algumas operações (como divisão por zero ou ler de um arquivo não-existente) produzem condições de erro ou exceções. Você pode até criar suas próprias exceções e lançá-las em momentos adequados.
Se nada é feito para tratar a exceção, seu programa termina e mostra uma mensagem de erro. Você pode evitar isto com uma construção try/except. Por exemplo:
{{{
#!python
def divisao_segura(a,b):
try:
return a/b
except ZeroDivisionError:
return None
}}}
{{{ZeroDivisionError}}} é uma exceção padrão. Neste caso, você poderia ter verificado se b era zero, mas em muitos casos, esta estratégia não é viável. Além disso, se não tivermos a cláusula try em divisao_segura, e dessa forma tornando arriscada a sua chamada, nós poderíamos ainda fazer alguma coisa assim:
{{{
#!python
try:
divisao_insegura(a,b)
except ZeroDivisionError:
print "Foi tentada uma divisão por zero em divisao_insegura"
}}}
Nos casos onde normalmente não haveriam problemas específicos, mas eles poderiam ocorrer, o uso de exceções evita tediosos testes, etc.
Bem - era isto. Espero que você tenha aprendido alguma coisa. Agora pode ir [[http://www.python.org/|brincar]]. E lembre-se do lema do aprendizado em Python: "Use os fontes, Lucas." (Tradução: leia todo código fonte a que você tiver acesso :-)) Para começar, aqui está um [[http://www.idi.ntnu.no/~mlh/python/quicksort.py|exemplo]]. É o conhecido algoritmo QuickSort, de Hoare. Uma versão com a sintaxe destacada em cores está [[http://www.idi.ntnu.no/~mlh/python/quicksort.html|aqui]].
Vale a pena mencionar uma coisa sobre este exemplo. A variável done controla se partition foi finalizada, ou não, na busca entre os elementos. Assim quando um dos dois laços internos querem terminar a sequência de trocas, eles atribuem 1 à variável done e interrompem-se a si próprios com break. Por que os laços internos usam done? Porque, quando o primeiro laço interno finaliza com um break, o laço seguinte só será executado se done não estiver com o valor 1:
{{{
#!python
while not done:
while not done:
# Repete-se até ocorrer um break
while not done:
# Só executado se o primeiro não atribuir 1 para "done"
}}}
Uma versão equivalente, possivelmente mais clara, mas em minha opinião menos elegante que a anterior poderia ser:
{{{
#!python
while not done:
while 1:
# Repete-se até ocorrer um break
if not done:
while 1:
# Só executado se o primeiro não atribuir 1 para "done"
}}}
A única razão para eu usar a variável done no primeiro laço foi porque eu preferi manter a simetria entre os dois laços. Desta forma poderia ser invertida a ordem e mesmo assim o algoritmo funcionaria.
Mais alguns exemplos podem ser encontrados na página [[http://www.strout.net/python/tidbits.html|tidbit]] de Joe Strout.