Minicurso Python - Apresentado no JOLIM 2012

59
• Conceitos Básicos, Estruturas de Dados e Orientação a objetos Minicurso de Python Nathan Siegle Hartmann VIII JOLIM - Maringá, 2012 1

description

 

Transcript of Minicurso Python - Apresentado no JOLIM 2012

Page 1: Minicurso Python - Apresentado no JOLIM 2012

• Conceitos Básicos, Estruturas de Dados e Orientação a objetos

Minicurso de Python

Nathan Siegle Hartmann

VIII JOLIM - Maringá, 2012 1

Page 2: Minicurso Python - Apresentado no JOLIM 2012

O que é Python?O que é Python?• Python é uma linguagem de programação de altíssimo

nível (VHLPL – very high level programming language), interpretada, orientada a objetos e dinâmica criada por Guido van Rossum em 1991.

• A linguagem tem um modelo de desenvolvimento aberto mantido pela PSF (Python Software Foundation).

VIII JOLIM - Maringá, 2012 2

Page 3: Minicurso Python - Apresentado no JOLIM 2012

O que é Python?O que é Python?• A linguagem foi projetada com a filosofia de enfatizar

a importância do esforço do programador sobre o esforço computacional;

• Prioriza a legibilidade do código e a expressividade.

VIII JOLIM - Maringá, 2012 3

Page 4: Minicurso Python - Apresentado no JOLIM 2012

Quem usa Python?Quem usa Python?• Atualmente Python é uma das linguagens mais

utilizadas em grandes projetos no mundo. Engenheiros de software de empresas como Google afirmam que o uso de Python é essencial para o funcionamento de famosas ferramentas do Google. “C++ quando necessitamos, Python quando podemos”.

• As ferramentas Google Doc, Picasa, Orkut Help, dentre outras da empresa americana Google utilizam a linguagem Python.

VIII JOLIM - Maringá, 2012 4

Page 5: Minicurso Python - Apresentado no JOLIM 2012

Quem usa Python?Quem usa Python?• Grande parte da API do Google é desenvolvida em

Python;

• O Google App Engine (framework web online mantido pelo Google) oferece suporte total a Python e foi desenvolvido também em Python;

• Zope, um dos melhores servidores de aplicação da atualidade foi desenvolvido em Python;

• Linux tem diversar rotinas em Python.

VIII JOLIM - Maringá, 2012 5

Page 6: Minicurso Python - Apresentado no JOLIM 2012

Quem usa Python?Quem usa Python?• Empresas que patrocinam a Python Software

Foundation: ActiveState; ASTi; Array BioPharma, Inc.; BizRate.com; Canonical; CCP Games; cPacket Networks; EarnMyDegree.com; Enthought, Inc.; Google; HitFlip, Inc.; IronPort Systems; Madison Tyler LLC; Merfin LLC; Microsoft; O'Reilly & Associates, Inc.; Opsware, Inc.; Strakt Holdings, Inc.; Sun Microsystems; Tabblo; ZeOmega; Zope Corporation.

VIII JOLIM - Maringá, 2012 6

Page 7: Minicurso Python - Apresentado no JOLIM 2012

Por que usar Python?Por que usar Python?• Python é portável, você não precisa compilar seu

programa cada vez que muda de sistema operacional, basta apenas que exista um interpretador Python instalado.

• Python é open-source com licença flexível, há uma comunidade que desenvolve a linguagem, que está sempre aprimorando-a e qualquer um de nós pode fazer parte dessa comunidade. A licença flexível nos permite desenvolver softwares proprietários com ferramentas livres.

VIII JOLIM - Maringá, 2012 7

Page 8: Minicurso Python - Apresentado no JOLIM 2012

Por que usar Python?Por que usar Python?• Python é simples e auto-descritiva, algumas

linguagens de programação têm sintaxe complexa ou difícil de memorizar.

VIII JOLIM - Maringá, 2012 8

Page 9: Minicurso Python - Apresentado no JOLIM 2012

Resumo de Resumo de característicascaracterísticas

• Case sensitive;

• Tipagem dinâmica;

• Linguagem pura: 100% orientada a objetos;

• Código auto-descritivo: simples e de fácil leitura;

• Programação em alto-nível: não permite manipulação de ponteiros;

• Não suporta sobrecarga de funções;

VIII JOLIM - Maringá, 2012 9

Page 10: Minicurso Python - Apresentado no JOLIM 2012

SintaxeSintaxeif x > y:

big = x

small = y

else:

big = y

small = x

if x > y:

big = x

small = y

else:

big = y

small = x

Simples e objetivo! Não é preciso saber programação para entender este código, basta um conhecimento básico em inglês!

#comentário de uma linha

“““comentário de um bloco“““

‘‘‘comentário de um bloco‘‘‘

#comentário de uma linha

“““comentário de um bloco“““

‘‘‘comentário de um bloco‘‘‘

VIII JOLIM - Maringá, 2012 10

Page 11: Minicurso Python - Apresentado no JOLIM 2012

VariáveisVariáveis• O conceito de variável em Python é representado

sempre por um objeto. Na verdade, Python é uma linguagem pura, ou seja, tudo em Python é um objeto.

• Toda variável é uma referência!

• Variáveis armazenam endereços de memória e não valores!

VIII JOLIM - Maringá, 2012 11

Page 12: Minicurso Python - Apresentado no JOLIM 2012

OperadoresOperadores• Os operadores do Python:

Aritméticos Comparação Lógicos

+ == and

- != or

* > not

/ <

** >=

<=

in

is

VIII JOLIM - Maringá, 2012 12

Page 13: Minicurso Python - Apresentado no JOLIM 2012

Procedimentos e Procedimentos e FunçõesFunções

• Procedimentos não retornam valores

• Funções retornam valores

def procedimento():print “Hello World”

def procedimento():print “Hello World”

def hora():from datetime import datetimereturn datetime.now()

def hora():from datetime import datetimereturn datetime.now()

VIII JOLIM - Maringá, 2012 13

Page 14: Minicurso Python - Apresentado no JOLIM 2012

Procedimentos e Procedimentos e FunçõesFunções

• Valores padrão (Default)• Se nenhum valor for passado como parâmetro, é

assumido o valor padrão

def teste(var = 1):return var+1

def teste(var = 1):return var+1

VIII JOLIM - Maringá, 2012 14

Page 15: Minicurso Python - Apresentado no JOLIM 2012

Exemplo 1Exemplo 1

VIII JOLIM - Maringá, 2012 15

Page 16: Minicurso Python - Apresentado no JOLIM 2012

StringsStrings• A string em Python é representada pela classe str.

Toda string possui estado e comportamento provido pela classe str.

• Podem ser representadas utilizando “ ou ‘.

• Ex: “Meu nome é Nathan”.

• Ex: ‘Meu nome é Nathan’.

• Ex: “Meu nome é ‘Nathan’”

VIII JOLIM - Maringá, 2012 16

Page 17: Minicurso Python - Apresentado no JOLIM 2012

StringsStrings• Conheceremos agora alguns métodos para trabalhar

com strings:o __len__(): Retorna o tamanho da string;o capitalize(): Retorna a mesma string com a primeira

letra em maiúsculo.o upper(): Retorna a mesma string com todas as

letras em maiúsculo.o lower(): Retorna a mesma string com todas as

letras em minúsculo.

VIII JOLIM - Maringá, 2012 17

Page 18: Minicurso Python - Apresentado no JOLIM 2012

StringsStrings• Mais métodos:

o replace(antigo, novo): Retorna a mesma string com o valor novo em todas as ocorrências de antigo.

o split([separador]): Retorna uma lista de strings. Caso o separador não seja especificado, a lista será dividida por espaços em branco.

VIII JOLIM - Maringá, 2012 18

Page 19: Minicurso Python - Apresentado no JOLIM 2012

Exemplo 2Exemplo 2• Criptografar uma string, substituindo todas as

ocorrências de um ou mais elementos por símbolos especiais.

• Por exemplo: Substituir a ocorrência do símbolo “a” pelo símbolo “*”.

VIII JOLIM - Maringá, 2012 19

Page 20: Minicurso Python - Apresentado no JOLIM 2012

Lendo e Escrevendo Lendo e Escrevendo em Arquivosem Arquivos

• Leitura de arquivos em Python é simples como em C!

• Arquivos são objetos do tipo file;

• Para a abertura de um arquivo, utilizamos a função open;

• A função open funciona como uma fábrica de instâncias.

VIII JOLIM - Maringá, 2012 20

Page 21: Minicurso Python - Apresentado no JOLIM 2012

Formas de Abrir um Formas de Abrir um ArquivoArquivo

• Read: Abre o arquivo para leitura.• Write: Abre o arquivo para escrita. Cria uma nova

instância do arquivo a cada vez.• Append: Abre o arquivo para complementar. Cria

um arquivo apenas se ele não existir• (Variantes).

variável = open(file,mode)...variável.close()

variável = open(file,mode)...variável.close()

VIII JOLIM - Maringá, 2012 21

Page 22: Minicurso Python - Apresentado no JOLIM 2012

Métodos para Métodos para leituraleitura

• Read: Lê todo o arquivo e retorna uma única string;

• Readline: Lê uma única linha do arquivo;• Readlines: Lê todo o arquivo e retorna um array

de linhas.

VIII JOLIM - Maringá, 2012 22

Page 23: Minicurso Python - Apresentado no JOLIM 2012

Métodos para Métodos para EscritaEscrita

• Write: Escreve uma string no arquivo, sequencialmente.

• WriteLines: Escreve um array de string, sequencialmente.

VIII JOLIM - Maringá, 2012 23

Page 24: Minicurso Python - Apresentado no JOLIM 2012

Exemplo 3Exemplo 3• 1 - Criar um arquivo para escrita e escrever nele;• 2 – Abrir o arquivo para leitura e verificar o

conteúdo existente;• 3 – Complementar o arquivo utilizando o modo

append.

VIII JOLIM - Maringá, 2012 24

Page 25: Minicurso Python - Apresentado no JOLIM 2012

Estruturas de DadosEstruturas de Dados• Estruturas de dados englobam tipos compostos e

dados complexos;

• As estruturas de dados mais famosas são vetores e matrizes. Dentre as mais avançadas, a mais conhecida é a lista.

• Há ainda outras estruturas como árvore, pilha, fila, hash, etc.

• Vale lembrar que uma string também é uma estrutura de dados!

• Estudaremos três estruturas: List, Tuple e Dict.

VIII JOLIM - Maringá, 2012 25

Page 26: Minicurso Python - Apresentado no JOLIM 2012

Estruturas de Dados: Estruturas de Dados: ListList

• A list (lista) é uma das mais conhecidas estruturas de dados.

• Em Python, a lista tem estado e comportamento que faz uma espécie de mistura entre o comportamento de vetores (acesso rápido por índices) e listas (“iterabilidade”);

VIII JOLIM - Maringá, 2012 26

Page 27: Minicurso Python - Apresentado no JOLIM 2012

Estruturas de Dados: Estruturas de Dados: ListList

• Veremos agora alguns métodos para trabalhar com listas:o append(elemento): adiciona elemento ao fim da

lista.o count(elemento): retorna um inteiro contendo a

quantidade de vezes que elemento aparece na lista.

o reverse(): inverte a ordem dos elementos da lista.o remove(elemento): remove da lista o primeiro

elemento encontrado.

VIII JOLIM - Maringá, 2012 27

Page 28: Minicurso Python - Apresentado no JOLIM 2012

Exemplo 4Exemplo 4• Trocar linhas por colunas de uma matriz quadrada.

• Verificar se um número é primo.

VIII JOLIM - Maringá, 2012 28

Page 29: Minicurso Python - Apresentado no JOLIM 2012

Gerando ListasGerando Listas• Python possui formas de gerar listas, veremos duas;

• Uma das primeiras funções que todos aprendem em Python é a função range, que gera uma lista de inteiros;

VIII JOLIM - Maringá, 2012 29

Page 30: Minicurso Python - Apresentado no JOLIM 2012

Gerando ListasGerando Listas

lista1 = range(1500)

lista2 = range(1001, 2000)

Gera uma lista de 0 até 1499.

Gera uma lista de 1001 até 1999.

VIII JOLIM - Maringá, 2012 30

Page 31: Minicurso Python - Apresentado no JOLIM 2012

Gerando ListasGerando Listas• Há ainda uma forma “avançada” de gerar listas a

partir de outras listas;

• Trata-se da técnica List Comprehension (Compreensão de Listas);

• A sintaxe de List Comprehension vem da linguagem funcional Haskell;

• O nome e a sintaxe originam da Matemática: Compreensão de listas tem sintaxe praticamente igual à notação axiomática de compreensão (Teoria de Conjuntos);

VIII JOLIM - Maringá, 2012 31

Page 32: Minicurso Python - Apresentado no JOLIM 2012

Exemplo 5Exemplo 5• 1 – Criar um vetor B que não contenha as

ocorrências de um elemento em um vetor Ao A = [1,2,3,1,2,3,1,2,3,4,5,6]

• 2 - Criar um array que contenha todos os elementos múltiplos de 3, 5 e 9 (simultaneamente) entre 0 e 10.000.

VIII JOLIM - Maringá, 2012 32

Page 33: Minicurso Python - Apresentado no JOLIM 2012

Estruturas de Dados: Estruturas de Dados: DictDict

• Chamaremos dicts de dicionários, para facilitar a fala em português;

• Um dicionário é uma estrutura de dados onde cada nó é composto por uma chave e um valor;

• Têm este nome pois são praticamente a mesma coisa que um dicionário!

VIII JOLIM - Maringá, 2012 33

Page 34: Minicurso Python - Apresentado no JOLIM 2012

Estruturas de Dados: Estruturas de Dados: DictDict

dicionario = {}dicionario["teste"] = "A palavra teste significa que estamos testando"dicionario["testado"] = "A palavra testado significa que algo jah passou por um teste"dicionario["testando"] = "A palavra testando significa que algo estah passando por um teste"

dicionario = {}dicionario["teste"] = "A palavra teste significa que estamos testando"dicionario["testado"] = "A palavra testado significa que algo jah passou por um teste"dicionario["testando"] = "A palavra testando significa que algo estah passando por um teste"

pessoas = {"Maria" : "Nome antigo", "Shyana" : "Nome complicado"}

VIII JOLIM - Maringá, 2012 34

Page 35: Minicurso Python - Apresentado no JOLIM 2012

Estruturas de Dados: Estruturas de Dados: DictDict

• Alguns métodos de manipulação de dicionários:o get(indice): retorna o valor correspondente a indice.o items(): retorna uma lista de tuplas, no formato

(índice, valor).o values(): retorna uma lista com todos os valores do

dicionário.o keys(): retorna uma lista com todas as chaves do

dicionário.o clear(): remove todos os itens do dicionário.

VIII JOLIM - Maringá, 2012 35

Page 36: Minicurso Python - Apresentado no JOLIM 2012

Estruturas de Dados: Estruturas de Dados: DictDict

pessoas = {"Maria" : "Nome antigo", "Shyana" : "Nome complicado"}

print(pessoas.get("Maria"))print(pessoas.items())print(pessoas.values())print(pessoas.keys())pessoas.clear()print(pessoas)

pessoas = {"Maria" : "Nome antigo", "Shyana" : "Nome complicado"}

print(pessoas.get("Maria"))print(pessoas.items())print(pessoas.values())print(pessoas.keys())pessoas.clear()print(pessoas)

VIII JOLIM - Maringá, 2012 36

Page 37: Minicurso Python - Apresentado no JOLIM 2012

UtilizaçãoUtilização• Muito útil para arrays esparços.• Hashing.• Etc.

VIII JOLIM - Maringá, 2012 37

Page 38: Minicurso Python - Apresentado no JOLIM 2012

Exemplo 6Exemplo 6• Criar um dicionário com as pessoas Ana, Bruna,

Carolina atribuindo suas respectivas idades: 20, 19, 18 anos.

VIII JOLIM - Maringá, 2012 38

Page 39: Minicurso Python - Apresentado no JOLIM 2012

RecursãoRecursão• Recursão é uma forma alternativa à tradicional

para desenvolver programas de computador.• Algumas versões recursivas são mais eficientes

que imperativas e até mesmo mais simples de se implementar.

VIII JOLIM - Maringá, 2012 39

Page 40: Minicurso Python - Apresentado no JOLIM 2012

RecursãoRecursão

def funcaoRecursiva(variavel):if variavel == 10:

return variavel #caso basereturn variavel + funcaoRecursiva(variavel+1)#chamada recursiva

def funcaoRecursiva(variavel):if variavel == 10:

return variavel #caso basereturn variavel + funcaoRecursiva(variavel+1)#chamada recursiva

VIII JOLIM - Maringá, 2012 40

Page 41: Minicurso Python - Apresentado no JOLIM 2012

Exemplo 7Exemplo 7• Calcular o fatorial de um número utilizando uma

função recursiva e também uma versão não recursiva.

• Comparar a complexidade de implementação.

VIII JOLIM - Maringá, 2012 41

Page 42: Minicurso Python - Apresentado no JOLIM 2012

DesafioDesafio• Criar um registro (utilizando arquivo) que

armazene diversas pessoas (Nome e idade) para uma pesquisa da universidade.

• Crie uma função que leia o arquivo e apresente na tela os devidos dados.

VIII JOLIM - Maringá, 2012 42

Page 43: Minicurso Python - Apresentado no JOLIM 2012

Orientação a Objetos em Orientação a Objetos em PythonPython

VIII JOLIM - Maringá, 2012 43

Page 44: Minicurso Python - Apresentado no JOLIM 2012

Orientação a objetosOrientação a objetos• Python é uma linguagem 100% orientada a objetos,

significa que tudo em Python é um objeto!

• Veremos nos próximos slides como definir classes, atributos, métodos e como aplicar em Python diversos conceitos da Orientação a Objetos.

VIII JOLIM - Maringá, 2012 44

Page 45: Minicurso Python - Apresentado no JOLIM 2012

Definindo ClassesDefinindo Classesclass Veiculo(object): def __init(self,parametro):

self.parametro = parametro

class Veiculo(object): def __init(self,parametro):

self.parametro = parametro

Palavra class tipicamente utilizada para definir classes! (:

Método inicializador da classe

VIII JOLIM - Maringá, 2012 45

Page 46: Minicurso Python - Apresentado no JOLIM 2012

Definindo AtributosDefinindo Atributos• Existem duas formas de definir atributos de instância

em Python;

class Veiculo(object): pass

fusca = Veiculo()fusca.marca = "Volkswagen"fusca.ano = 1972

class Veiculo(object): pass

fusca = Veiculo()fusca.marca = "Volkswagen"fusca.ano = 1972

class Veiculo(object): marca = None ano = None

gol = Veiculo()gol.marca = "Volkswagen"gol.ano = 2008

class Veiculo(object): marca = None ano = None

gol = Veiculo()gol.marca = "Volkswagen"gol.ano = 2008

VIII JOLIM - Maringá, 2012 46

Page 47: Minicurso Python - Apresentado no JOLIM 2012

Definindo AtributosDefinindo Atributosclass Veiculo(object): marca = None ano = None

gol = Veiculo()gol.marca = "Volkswagen"gol.ano = 2008gol.bazinga = True

class Veiculo(object): marca = None ano = None

gol = Veiculo()gol.marca = "Volkswagen"gol.ano = 2008gol.bazinga = True

VIII JOLIM - Maringá, 2012 47

Page 48: Minicurso Python - Apresentado no JOLIM 2012

AtributosAtributos• Nem sempre queremos que os atributos sejam

acessados diretamente• Para isso podemos criar métodos Getters e

Setters

• Ainda podemos tornar os atributos privados

Pessoa.getNome()Pessoa.setNome(nome)Pessoa.getNome()Pessoa.setNome(nome)

Pessoa.__nome = “nome”Pessoa.__idade = idadePessoa.__nome = “nome”Pessoa.__idade = idade

VIII JOLIM - Maringá, 2012 48

Page 49: Minicurso Python - Apresentado no JOLIM 2012

Definindo métodosDefinindo métodos• Um método é um atributo com comportamento;

• Para não fundir conceitos, vamos apenas trabalhar com métodos da forma tradicional, ou quase isso;

• Para definir métodos e funções em Python utilizamos a palavra reservada def;

• Def __init__(self,atr1,atr2)

• Def getNome(self): return self.__nome

VIII JOLIM - Maringá, 2012 49

Page 50: Minicurso Python - Apresentado no JOLIM 2012

Herança de classesHerança de classesclass Atleta(Pessoa): peso = None aposentado = None

def __init__(self, nome, idade, peso): super(Atleta, self).__init__(nome, idade) self.peso = peso self.aposentado = False

def aquecer(self): print("Atleta aquecido!")

def aposentar(self): self.aposentado = True

class Atleta(Pessoa): peso = None aposentado = None

def __init__(self, nome, idade, peso): super(Atleta, self).__init__(nome, idade) self.peso = peso self.aposentado = False

def aquecer(self): print("Atleta aquecido!")

def aposentar(self): self.aposentado = True

VIII JOLIM - Maringá, 2012 50

Page 51: Minicurso Python - Apresentado no JOLIM 2012

Herança de classesHerança de classesclass Corredor(Atleta): def correr(self): print("Corredor correndo!")

class Corredor(Atleta): def correr(self): print("Corredor correndo!")

class Ciclista(Atleta): def pedalar(self): print("Ciclista pedalando!")

class Ciclista(Atleta): def pedalar(self): print("Ciclista pedalando!")

class Nadador(Atleta): def nadar(self): print("Nadador nadando!")

class Nadador(Atleta): def nadar(self): print("Nadador nadando!")

VIII JOLIM - Maringá, 2012 51

Page 52: Minicurso Python - Apresentado no JOLIM 2012

Herança múltiplaHerança múltipla• Há uma peculiaridade no diagrama de classes: a classe

TriAtleta herda de três outras classes;

• Muitas pessoas podem pensar: mas isso é impossível!

• Em Python, assim como em C++, isso é possível sim! Logo, a classe TriAtleta fica bem simples:

class TriAtleta(Ciclista, Nadador, Corredor): passclass TriAtleta(Ciclista, Nadador, Corredor): pass

VIII JOLIM - Maringá, 2012 52

Page 53: Minicurso Python - Apresentado no JOLIM 2012

Exemplo 8Exemplo 8• Criar uma classe Estudante, com atributo curso.

Esta classe deve herdar da classe Pessoa os atributos nome e idade.

• Uma pessoa tem um carro. Criar uma classe Carro e fazer que uma pessoa tenha um atributo do tipo Carro.

VIII JOLIM - Maringá, 2012 53

Page 54: Minicurso Python - Apresentado no JOLIM 2012

ExceçõesExceções• Em Python, assim como em C++ e Java, o conceito de

Exceção está ligado à orientação a objetos.

• Uma exceção é um objeto, possui estado e comportamento.

• O tratamento de exceções pode ser utilizado para aumentar o nível de abstração do código.

• É possível usar exceções também para encapsular dados específicos sobre o erro levantado.

• Vamos aprender como criar, tratar e levantar uma exceção em Python!

VIII JOLIM - Maringá, 2012 54

Page 55: Minicurso Python - Apresentado no JOLIM 2012

ExceçõesExceções• Primeiramente, vamos criar nossas exceções.

• Uma exceção personalizada é modelada por uma classe qualquer, que herda da classe BaseException;

• Nas versões anteriores de Python qualquer classe podia modelar uma exceção. Isso gerava a má prática de lançar exceções modeladas pela classe string;

VIII JOLIM - Maringá, 2012 55

Page 56: Minicurso Python - Apresentado no JOLIM 2012

ExceçõesExceções

def alterarPeso(self, peso): if peso > 0 and peso < 400: self.__peso = peso else: raise Exception("%f nao eh um peso valido!", %(peso))

def alterarPeso(self, peso): if peso > 0 and peso < 400: self.__peso = peso else: raise Exception("%f nao eh um peso valido!", %(peso))

VIII JOLIM - Maringá, 2012 56

Page 57: Minicurso Python - Apresentado no JOLIM 2012

ExceçõesExceções• Python levanta diversas exceções internamente:

ValueError, IOError, TypeError;

• Vamos tratar exceções!

• Para tratar exceções em Python utilizamos try… except… else… finally;

VIII JOLIM - Maringá, 2012 57

Page 58: Minicurso Python - Apresentado no JOLIM 2012

ExceçõesExceçõesdef incrementar(numero):

try:

return numero+1

except:

raise Exception(“É necessário um número para somar”)

def incrementar(numero):

try:

return numero+1

except:

raise Exception(“É necessário um número para somar”)

def incrementar(numero):

try:

return numero+1

except TypeError:

return int(numero)+1

def incrementar(numero):

try:

return numero+1

except TypeError:

return int(numero)+1

VIII JOLIM - Maringá, 2012 58

Page 59: Minicurso Python - Apresentado no JOLIM 2012

ReferênciasReferências• www.python.org

• www.pythonbrasil.org

• www.djangobrasil.org

• www.plone.org

• www.tchezope.org

VIII JOLIM - Maringá, 2012 59