Olí a todos!
Resolvi fazer este tutorial sobre Python por duas razões:
1º Sou programador em Python desde Setembro de 2006
2º Python é simples, elegante e poderoso (em alguns casos mais poderoso e eficiente que a linguagem de programação C)
1 Introdução
A linguagem Python é uma linguagem de alto nàvel, interpretada, orientada a objetos com uma semântica dinâmica. Suas estruturas de alto nàvel, combinadas com sua tipagem de amarração dinâmica a faz muito atrativa para desenvolvimento de largos aplicativos assim como para uso como linguagem de script ou de colagem.
A sintaxe simples do Python eoncoraja a reutilização de código simplificando a manutenção e a normalização de dados em módulos e pacotes distintos.
Esta linguagem, bem como seu código fonte, se encontram gratuitamente disponàvel na Internet podendo ser vasculhados por qualquer interessado sen ônus algum. Apesar disto, a linguagem Python é marca registrada do Stichting Mathematisch Centrum de Amsterdam. Todos os direitos reservados.
A linguagem Python foi desenvolvida pelo holandês Guido Van Rossun, no final de 1990. Segundo Van Rossum, a linguagem surgiu enquanto este passava o tempo entre o Natal de 1990 e o ano novo de 1991, mexendo na linguagem ABC, a qual ele havia participado do grupo que a desenvolvera. Jí no começo de 1991, Van Rossum jí havia feito uma especificação bastante próxima a esta feita neste texto.
Hoje a linguagem Python vem sendo utilizada por milhares de pessoas ao redor do mundo, sendo sustentada por uma fundação, a CNRI, e por um sem número de voluntírios ao redor do mundo, unidos via Internet, formandoa Python Software Activity (PSA). Neste momento estí sendo proposta a criação de um movimento chamado Python Consortium que tem por objetivo passar o fomento da linguagem para um pool de empresas e instituições de ensino e pesquisa. Esta proposta estí sendo apresentada na Sétima conferência Internacional da Linguagem Python que aconteceu agora em novembro, em Houston, Texas.
De volta ao artigo, vamos à seguir iniciar o trabalho de anílise léxica da linguagem. Você observarí que o texto não serí baseado em metodologias formais de especificação de linguagens, como a BNF, dand portanto, margens para ambiguidades. Mas como o texto é de caríter ilustrativo o autor escolheu a linguagem natural como o melhor formato para apresentí-lo.
2 Anílise Léxica
O interpretador Python interpreta senteças recebidas de algum dispositivo de entrada (console ou arquivo), Esta entrada é lida pelo analizador léxico que divide o código recebido em tokens, repassando-o para o parser que interpreta o programa.
O Python é totalmente definido utilizando a tabela ASCII de 7 bits.
2.1 Linhas
Um programa em Python é dividido em linhas lógicas. Estas linhas lógicas são separadas pelo token NEWLINE e pode ser construàda por uma ou mais linhas fàsicas. Estas linhas fàsicas são trechos de programas divididos pelo caractere ENTER.
Uma linha lógica não pode ultrapassar uma linha fàsica com exceção de dois casos especiais. O primeiro caso é o ajuntamento explàcito de linhas quando um caractere de barra invertida é posto no final da linha.
soma = a + b + c + d + e + f + g \
h + i + j + k + l + m
O segundo é o ajuntamento implàcito de linhas que ocorre dentro de expressões delimitadas por colchetes, parênteses ou chaves, como no exemplo abaixo.
dias_da_semana = ['dom','seg','ter',
'qua','qui','sex','sab']
Os comentírios são identificados pelo sàmbolo hash (#). todo o conteúdo de uma linha que estiver a direita deste sàmbolo é desconsiderado. O comentírio só vale na linha que contém o hash. As linhas totalmente em branco são disconsideradas pelo interpretador.
2.2 Identação
Uma peculiaridade do Python é a de não possuir terminadores de bolcos explàcitos, como begin e end no Pascal, ou { e } no C. Ao invés disto o Python utiliza a própria identação do programa como referência para que o analizador léxico determine o escopo dos blocos. Neste conceito, cada linha lógica possui um valor chamado de nàvel de identação que é o número da primeira coluna não branca da linha. Os delimitadores de blocos são chamados de INDENT e DEDENT, e são encontrados através de uma pilha como descrito abaixo.
Antes que a primeira linha do arquivo seja lida, um zero é posto numa pilha, este zero não mais sairí da pilha. Os números postos na pilha irão sempre crescer do fundo até o topo da pilha, ou seja, cada novo valor na pilha é sempre maior que o valor anterior. No começo de cada linha lógica, o nàvel de identação é comparado como o número do topo da pilha. Se este número for igual, a pilha é permanece inalterada, Se o número for maior, a pilha recebe o valor do nàvel de identação da linha e um delimitador INDENT é adicionado. Se o nàvel de indentação for menor que o valor da pilha, a pilha é sucessivamente desempilhada até que se encontre na pilha o valor do nàvel da linha. e este valor não for encontrado o interpretador acusa um erro de sintaxe. Para cada valor que sai da pilha é adicionado um identificador DEDENT.
À seguir um programa onde são mostrados os delimitadores de linhas e blocos.
def perm(1): NEWLINE
# Compute the list for all permutations of 1
INDENT if len(l)<=1: NEWLINE
INDENT return[1] NEWLINE
DEDENT r=[] NEWLINE
for i in range(len(l)): NEWLINE
INDENT s=l[:i]+ \
l[i+1:] NEWLINE
p=perm(s) NEWLINE
for x in p: NEWLINE
INDENT r.append (l[i:i+1]+x) NEWLINE
DEDENT
DEDENT return r
DEDENT
Vemos agora um exemplo com vírio erros de identação:
def perm(l): # primeira linha identada
for i in range (len(l)): # não identada
s=l[:i]+l[i+1:]
p = perm (s) # identação inesperada
for x in p:
r.append(l[i:i+1]+x)
return r # dedentação inconsistente
2.3 Outros tokens
Identificadores
uma letra seguido quantas letras ou números, ou barrasbaixas se desejar.
Palavras-chave
as palavras chave são as seguntes
and assert break class continue
def del elif else except
exec finally for from global
if import in is lambda
not or pass print raise
return try while
Classes Reservadas de Identificadores
alguns identificadores com significados especiais. eles são reconhecàveis pelas seguintes míscaras: _* (não importível), __*__ (nome definido pelo sistema), __* (nome privado de uma classe).
Srings
uma string é uma cadeia de caracteres delimitada por aspas simples ou aspas duplas. tabém são vílidos os scape characters ao estilo da linguagem C. As strings precedidas por um ``r'' maiúsculo ou minúsculo consideram os caracteres de escape como caracteres comuns.
Números inteiros
Uma sequência de dàgitos decimais, sucedidos de ``X'' se hexadecimal, ou precedido de ``0'' (zero) se octal. Ou seja 123 é um número inteiro decimal, jí 0123 é um número inteiro octal.
Inteiros longos
são número sinteiros sucedidos da letra ``L'', maiúscula ou minúscula.
Números de ponto flutuante
é um número inteiro seguido por im separador decimal ``.'' e uma parte fracioníria. Pode-se usar a notação de base dez com a letra ``E''.
Numeros imaginírios
é um número de ponto flutuante seguido da letra ``J''.
Operadores
+ - * ** / %
<< >> & | ^ ~
< > <= >= == != <>
Delimitadores
( ) [ ] { }
, : . ' = ;
Caracteres com significados dependentes do contexto
' `` # \
Caracteres totalmente invílidos
fora de strings, estes caracteres geram erro sintítico imediato.
@ $ ?
3 Modelo de Dados
Objetos são a abstração do Python para todas as estruturas de dados. Todo programa em Python é composto por objetos ou por relação entre objetos.
Todo objeto tem uma identidade, que lhe é atribuàda na sua criação e não pode ser mudada. O tipo do objeto també é imutível. Este tipo define as operações que podem ser efetuadas neste objeto. Os objetos também possuem um valor que pode ser de tipo mutível (listas, tuplas, etc.) ou imutível (números e strings).
Os objetos de Python, uma vez criados, não podem ser destruàdos. O que ocorre normalmente é que o interpretador possui um serviço de limpeza automítica de memória que finaliza todo o objeto que não é mais alcançível. Por exemplo: suponha um objeto ``a'' que representa uma grande estrutura de dados. Se a este objeto for atribuàdo um objeto de tamanho pequeno, como por exemlo um inteiro, toda aquela estrutura de dados a ele associado anteriormente é finalizada e o espaço de memória é liberado. Esta função é extensàvel à tipos mais complexos como arquivos, apesar de que sua utilização não é aconselhada pelos prórpios criadores da linguagem devido ao baixo nàvel de abstração que oferece.
Veremos à seguir os tipos padão da linguagem Python. Devido a caracteràstica aberta da linguagem, estes tipos podem ser extendidos com extensões da linguagem em C.
None
é o tipo nulo. pode ser invocado pelo identificador None e indica ausência de sentença. Seu valor lógico é falso.
Ellipsis
é um valor identificado pelo nome Ellipsis. e significa ``...'' (????). Seu valor lógico é verdadeiro.
3.1 Números
São criados por literais numéricos ou são retornados por funções ou operações aritméticas. Objetos numéricos são imutíveis.
Números inteiros
são objetos que representam o conjunto matemítico dos números inteiros.
Inteiros simples
são inteiros de 32 bits de precisão finita. Englobam a faixa de -2147483648 até 2147483647 que pode ser maior dependendo do processador e do sistema operacional. Um resultado fora desta faixa retorna um erro de Overflow. Não ocorre a perda do bit mais significativo fazendo com que o valor caia sempre dentro desta faixa. A representação biníria do inteiro simples é em forma de complemento-2 .
...-1000,-1001,...,-3,-2,-1,0,1,2,3,...,1000,1001,...
0100 # octal
0x12 # hexadecimal
Interios longos
é uma outra classe de inteiros com faixa de abrangência ilimitada, ou limitada apenas pela memória da míquina. Uma operação bit-à-bit vílida para os inteiros simples também é valida para os inteiros longos.
767468641767451361273676485352135L
fatorial (10000L) #acredite, eh BEM maior do que todo este texto.
Números de ponto flutuante
representam valores reais de precisão dupla (64 bits). os numeros de precisão simples não são utilizados porque, devido a estrutura de dados internamente complexa do Python, o projetista da linguagem concluiu que a economia de alguns bits é completamente sem propósito.
3.1415
1. # o ponto no numero inteiro serve para identificar um objeto como ponto flutuante
0.00000000231
Números complexos
são representados por um par de números de ponto flutuante, os quais podem ser extraàdos independentemente pelos métodos real e imag.
>> complex (1,2)
(1+2j)
>> 3 + 1j*3
(3+3j)
3.2 Sequências
São objetos que representam uma sequência ordenada e finita de objetos. A função len () retorna o número de elementos de uma determinada sequência. As sequências são indexadas e podem ser recuperadas por um esquema de àndices por exemplo:
a = [i:j]
rertorna todos os elementos cujos àndices estão compreendidos no intervalo i <= k < j.
Sequências imutíveis
são sequências que não podem ser extendidas. São elas as strings e as tuplas:
Strings
são cadeias de caracteres. São validos quaisquer caracteres da tabela ASCII.
'Isto eh uma string'
``Isto tambem eh uma string''
``That's cool!''
'''Isto eh uma string de tamanho ilimitado'''
'Isto eh uma string como um carctere <ENTER>\n'
r'Isto eh uma string com uma barra invertida e um n \n'
Tuplas
é um conjunto dois ou mais objetos de tipos arbitrírios, separados por vàrgula.
(1, 2.3, [3,4,5], 'abacaxi')
Sequências Mutíveis
são sequências compostas de objetos que podem ser alteradas mesmo após serem criadas. Os tipos mutíveis disponàveis são:
Listas
os elementos de uma lista são objetos arbitrarios em Python. Uma lista é definida por sendo uma sucessão de objetos separados por vàrgula e delimitados por colchetes. Não existem casos especias para tratamento de listas vazias ou listas unitírias.
[1,2,3]
['a', 0, 124111122L]
[[1,2],[3,4],[5,6]]
Mapeamentos (mappings)
são estruturas de dados que podem ser indexadas por um chave de qualquer tipo. No caso da lista, os únicos àndices vílido são números inteiros que significam a posição do elemento indexado dentro da própria lista, jí no caso dos objetos mappings este àndice pode ser de qualquer tipo.
Dicionírios
o único objeto tipo mapeamento atualmente disponàvel em Python é o dicionírio. Estes são elementos que podem adotar como àndice qualquer objeto imutível. Isto ocorre porque a indexação destes objetos ocorre por comparação de valor e não de referência, o que certamente iria de encontro a abstração proposta pelo tipo. Os dicionírios são sequências de ``n'' objetos separados por vàrgula e delimitados por chaves, tal que ``n'' é um número inteiro. Os elementos de àndice impar desta sequência são as chaves e os elementos de àndice par são são os objetos indexados pelas chaves propostas.
{'nome': 'Jose' , 'idade':54 , 23:[1,2,3,4,5] , 3.14:None}
3.2.1 Uma explanação sobre as sequências mutíveis
Pode haver confusão em declarar que ua string é uma estrutura imutível posto que são vílidas operações do tipo
a = ``Rolling ``
a = a + ``Stones''
Quando fazemos uma atribuição à uma string estamos redefinindo o seu valor, ou seja, na primeira linha o objeto ``a'' recebe a string `` Rolling ``, que por sua vez é uma constante (ou um objeto imutível na terminologia adotada pelo Python). Na segunda expressão, o objeto recebe o valor de ``a'', ou seja, a constante ``Rolling ``, concatenada a constante ``Stones'', que são, na verdade, um novo objeto. Desta forma o objeto string não é mutível!
Na sentença à seguir ocorre uma opreração completamente diferente.
a = [1,2]
a = a + [3,4]
Neste caso o objeto ``a'' recebe na primeira expressão, a lista [1,2] que não é uma constante e sim uma construção composta de dois objetos imutíveis, ou em termos de implementação, um conjunto de dois ponteiros. Na segunda expressão, o objeto ``a'' recebe ele mesmo, ou seja, a cosntrução que ele estí referenciando, mais uma nova construção composta de dois objetos imutíveis.
Uma outra forma de definir objetos mutíveis e não mutíveis é definindo que nas operações feitas sobre os objetos mutíveis, estes objetos são passados por referência e nos não mutíveis são passados por valor.
3.3 Funções
Existem dois tipos de funções:
Funções definidas pelo usuírio
é um objeto criado por uma definição de função. Observe o código à seguir: A primeira função retorna o fatorial do número dado, a segunda retorna a potencia de base x e expoente n, observe os exemplos de utlização das funções.
def fatorial (n):
'retorna o fatorial de n'
if n == 0:
return 1
return n*fat (n-1)
def pot (x, n=2)
'retorna a potencia com base x e expoente n \
se n for ocultado eh assumido n = 2'
return x**n
print fat (10)
print fat (5000L) # inteiro longo
print pot (3,5)
print pot (8) # equivale a 8**2
Funções pre definidas (Built-in)
São funções que não são resultado de uma operação import, ou seja que jí estavam presentes quando da inicialização do interpretador. O usuírio pode escrever uma função built-in, escrevendo-a na linguagem C e incorporando-a ao próprio interpretador. A linguagem Python oferece vírios recursos de expansão neste sentido.
3.4 Classes
Um objeto classe é definido por uma definição de classe. Quando uma classe é atribuàda a outro objeto, este objeto passa a ser uma instância desta classe.Uma classe é composta por atributos que representam o seu estado interno ou fazem operações sobre este estado. Vejamos o exemplo abaixo:
from Tkinter import *
class App:
def __init__ (self):
self.i = 0
self.root = Tk()
self.button = Button (self.root, text = 'Hello', command = self.say_hi)
self.button.pack (side=LEFT)
self.root.mainloop()
def say_hi (self):
print 'Ola todos!'
self.i = self.i + 1
a = App()
O exemplo acima mostra a classe App. Esta classe cria uma janela com um botão com o texto 'Hello' que, quando pressionado, imprime a frase 'Ola todos!'. Esta classe é composta dos métodos __init__ e say_hi, e dos objetos root (a janela), button (o botão) e i (literal que conta o número de vezes que o botao foi pressionado). Os métodos definidos pelo usuírio dentro do objeto são as implementações das operações vílidas nos objetos desta classe. Estes objetos, por sua vez, representam o estado atual da classe.
Na última linha do observamos a atribuição de App à a. Neste ponto a tornou-se uma instância de App. Uma instância de uma Classe é obtida pela chamada desta classe como uma função. Quando isto ocorre, automaticamente é chamado o método __init__. Isto é um padrão da linguagem.
3.4.1 Diferença entre classe e instância
Uma classe é um objeto, porém é um objeto dito não amarrado (unbound), ou seja, não foi mapeado em memória um endereço para os métodos e os demais objetos internos a esta classe. Por outro lado, ima instância de uma classe é uma amarração (binding) de uma classe, ou seja, quando se instancia uma classe, atribuindo-a à um objeto, estí se alocando um espaço da memória para os elementos desta classe. No exemplo acima são vílidos as seguintes expressões no nàvel da instância a.
a.say_hi ()
print a.i #imprime o número de vezes que o botao foi pressionado
a.root.title ('Exemplo 1') # muda o tàtulo da janela
Isto não significa que os métodos de uma classe não sejam objetos executaveis, por exemplo, a expressão a.say_hi() é o mesmo do que App.say_hi(a).
3.4.2 Caracteràsticas internas das classes
Em Python as classes são construàdas através de uma estrutura de dicionírio no qual uma strings com os identificadores dos objetos são as chaves e os objetos em sà (métodos e atributos em geral) são os valores indexados por estas chaves.
O exemplo acima é representado pelo seguinte dicionírio (os números são aleatórios e seria sibstituàdos pelo endereço de memória dos objetos referidos pelos campos chave):
App = {'__init__':63233, 'say_hi':67542, 'root':63462, 'button':68382, 'i':68112}
3.4.3 Nomes Especiais de Métodos
Aqui é descrito como expressões definidas pelo usuírio podem customizar o comportamento de um determinado objeto. Vamos estudar alguns nomes padrão de métodos.
__init__
este método é invocado quando uma instância da classe é criada. Os argumetos da função são aqueles passados ao coustrutor de classe. Quando uma classe é derivada de outra, esta nova classe deve chamar explicitamente a função __init__ da classe herdada. Veja o exemplo:
class MyClass (OldClass):
def __init__ (self, data1, data2):
self.data1 = data1
self.data2 = data2
OldClass.__init__ (self, 0, 0)
def Op1 (self):
pass
def Op2 (self):
pass
X = MyClass (x, y)
__del__
este método é invocado quando a instância estí para ser destruàda, por exemplo:
class arquivo:
def __init__ (self, nomearq):
self.arq = open (nomearq, 'rw')
..........
def __del__ (self):
self.arq.close()
__repr__
retorna a representação em Python do objeto, ou seja, retorna o código fonte do objeto. Serve para recriarobjetos com o mesmo valor.
__call__
é invocada quando a instância é ``invocada'' como uma função. Quando este argumento existe, x(arg1, arg2,..) é uma forma contracta para x.__call__(arg1, arg2,...). Como em Python a abstração genérica de dados é o objeto, ou seja, a classe instanciada, todas as funções defindas são também objetos que contém este método que é invocado quando própria função é invocada. Observe o exemplo:
def riemann (expr, a, b):
x = a
somat = 0
norma = 0.0001
while x <= b:
somat = somat + eval (expr)* norma
x = x + norma
return somat
É estritamente a mesma coisa do que:
class riemann:
def __call__ (self, expr, a, b):
x = a
somat = 0
norma = 0.0001
while x <= b:
somat = somat + eval (expr)* norma
x = x + norma
return somat
3.5 Outros objetos
Módulos
são arquivos fonte de porgrama em Python que são importados por uma chamada de import. Também são tratadas como as classes e representadas por um dicionírio.
Arquivos
um objeto arquivo representa um arquivo aberto e é criados pelas funções open(), popen(), fdopen(), ou pelo método makefile() do objeto socket.
Código objeto
um dos objetos maos impressionantes do Python é o seu código objeto. Como jí foi dito o Python é uma linguagem interpretada mas sua execução não é feita linha-à-linha. Na realidade o interpretador gera um bytecode para as senteças recebidas. Este bytecode é a chave da portabilidade e do polimorfismo pois neste são vílidas operações do tipo recuperar os nomes dos objetos que o compoem ou mesmo o código fonte e que o gerou.
Frame
é um dicionírio que contam todos os tipos daquele nàvel de execução. Neste dicionírio estão descritos todos os objetos acessíveis naquele ponto do programa.Veja o exemplo:
x = 1
y = 2
nome = 'Mariazinha'
def troca (x, y):
'funcao que nao serve pra nada
aux = x
x = y
y = aux
# frame global
#{'x'=1,'y'=2, 'nome'='Mariazinha, 'troca' = funcao}
# frame na funcao troca
#{'x'=??, 'y'=??, aux=??, 'nome'='Mariazinha'}
Traceback
Um objeto traceback é uma pilha que é criada quando ocorreu uma exeção. Quando acontece uma exeção, o interpretador procura por um bloco de tratamento de exeções para isto ele começa a desempilhara srack trace, ou a plinha de execução. Á cada nIvel que é desempilhado o traceback rfecebe um elemento. Desta forma, pode-se saber em quantos nàveis abaixo do tratador é que houve a exeção.
Mais informações sobre a linguagem de programação Python:
http://www.pythonbrasil.com.br
:wink:


Responder com Citação
Muito Bom!



