Python
Python
23 de agosto de 2018
©75-18, Pedro Kantek 2 versão de 23 de agosto de 2018
Sumário
2 Linguagens de programação 21
2.1 Categorias de LP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.1.1 Quanto à geração . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.1.2 Quanto ao nivel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.1.3 Quanto à vocação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.1.4 Quanto à modalidade de uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.1.5 Quanto ao paradigma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.1.6 Quanto a liberdade de escrita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.1.7 Quanto à idade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.2 Assembler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.3 Fortran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.4 Lisp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.5 Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.6 Cobol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.7 APL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.8 Basic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.9 Clipper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.10 Natural . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.11 Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.12 C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.13 C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.14 Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.15 PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.16 J . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.17 Lua . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3 Python 35
3
5 Variáveis, sua entrada e saída 41
5.1 Atribuição . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.1.1 Atribuições malucas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.2 Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.2.1 Mudando o tipo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.2.2 Nomes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.3 Expressões aritméticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.4 Saída de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
5.4.1 Opções da função print . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
5.5 Entrada de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.5.1 Um programa completo usando input e print . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.6 Variáveis Lógicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
5.6.1 Expressões Lógicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
6 Comandos condicionais 51
6.1 Exercício . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
7 Repetições 57
7.1 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.2 break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.2.1 Repetição aninhada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.3 Continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.4 For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.5 Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
8 Listas 65
8.1 Fatiamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
8.1.1 fatiamento em arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
8.2 Mais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
8.3 Mais sobre listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
8.3.1 Usando listas como pilhas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
8.3.2 Usando listas como filas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
8.4 Ferramentas de programação funcional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
8.5 List comprehensions ou abrangências de listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
8.5.1 Listcomps aninhadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
8.6 O comando del . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
8.7 Tuplas e sequências . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
8.8 Sets (conjuntos) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
8.9 Dicionários . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
8.10 Técnicas de iteração . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
8.10.1 Métodos de dicionários . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
8.11 Mais sobre condições . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
8.12 Brincando com listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
9 Strings 81
9.0.1 String Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
9.0.2 String Formatting Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
9.0.3 Manipulação de bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
10 Funções 87
10.1 Mais sobre definição de funções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
10.1.1 Parâmetros com valores default . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
10.1.2 Listas arbitrárias de argumentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
10.1.3 Desempacotando listas de argumentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
10.1.4 Construções lambda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
10.1.5 Strings de documentação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
11 Objetos em Python 93
11.1 Um exemplo de objeto: um formigueiro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
11.1.1 Herança . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
12 Arquivos 97
12.1 Métodos de objetos arquivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
12.2 O módulo pickle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
26 Bibliografia 173
26.1 Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
26.2 Algoritmos e programação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
26.3 Métodos Numéricos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
Meu nome é Pedro Luis Kantek Garcia Navarro, conhecido como Kantek, ou Pedro Kantek. Nasci em Curitiba há mais
de 60 anos. Sou portanto brasileiro, curitibano e coxa-branca com muito orgulho, mas sendo filho de espanhóis (meus
7 irmãos nasceram lá), tenho também a nacionalidade espanhola. Aprendi a falar em castellano era o que se falava na
minha casa, o português é meu segundo idioma, só visto na escola. Estudei no Colégio Bom Jesus e quando chegou a
hora de escolher a profissão, lá por 1972, fui para a engenharia civil, mas sem muita convicção. As alternativas: medicina
(arghhh!) ou direito (arghhh! arghhh!).
Durante a copa do mundo de futebol de 1974 na Alemanha, ao folhear a Gazeta do Povo, achei um pequeno anúncio
sobre um estágio na área de processamento de dados (os nomes informática e computação ainda não existiam). Lá
fui eu para um estágio na CELEPAR, que acabou mais de 35 anos depois. Na CELEPAR fui de tudo: programador,
analista, suporte a BD (banco de dados), suporte a TP (teleprocessamento), coordenador de auto-serviço, coordenador
de atendimento, ... Minha carreira lá terminou na área de governo eletrônico. Desde cedo encasquetei que uma boa
maneira de me obrigar a continuar estudando a vida toda era virar professor. Comecei essa desafiante carreira em 1976,
dando aula num lugar chamado UUTT, que não existe mais. Passei por FAE, PUC e cheguei às Faculdades Positivo em
1988. Na década de 80, virei instrutor itinerante de uma empresa chamada CTIS de Brasília, e dei um monte de cursos
por este Brasil afora (Manaus, Recife, Brasília, Rio, São Paulo, Fortaleza, Floripa, ...). Em 90, resolvi voltar a estudar
e fui fazer o mestrado em informática industrial no CEFET. Ainda peguei a última leva dos professores franceses que
iniciaram o curso. Em 93 virei mestre, e a minha dissertação foi publicada em livro pela editora Campus (Downsizing
de sistemas de Informação. Rio de Janeiro: Campus, 1994. 240p, ISBN:85-7001-926-2). O primeiro cheque dos direitos
autorais me manteve um mês em Nova Iorque, estudando inglês. Aliás, foi o quarto livro de minha carreira de escritor,
antes já havia 3 outros (MS WORD - Guia do Usuário Brasileiro. Rio de Janeiro: Campus, 1987. 250p, ISBN:85-7001-
507-0, Centro de Informações. Rio de Janeiro: Campus, 1985. 103p, ISBN:85-7001-383-3 e APL - Uma linguagem de
programação. Curitiba. CELEPAR, 1982. 222p). Depois vieram outros. Terminando o mestrado, rapidamente para
não perder o fôlego, engatei o doutorado em engenharia elétrica. Ele se iniciou em 1994 na UFSC em Florianópolis. Só
terminou em 2000, foram 6 anos inesquecíveis, até porque nesse meio tive que aprender o francês - mais um mês em
Paris aprendendo-o. Finalmente virei engenheiro, 25 anos depois de ter iniciado a engenharia civil. Esqueci de dizer que
no meio do curso de Civil desistí (cá pra nós o assunto era meio chato...) em favor de algo muito mais emocionante:
matemática. Nessa época ainda não havia cursos superiores de informática. Formei-me em matemática na PUC/Pr em
1981. Em 2003, habilitei-me a avaliador de cursos para o MEC. Para minha surpresa, fui selecionado e virei delegado
do INEP (Instituto Nacional de Pesquisas Educacionais) do Governo Brasileiro. De novo, visitei lugares deste Brasilzão
que sequer imaginava existirem (por exemplo, Rondonópolis, Luiziânia, Rio Grande, entre outros), sempre avaliando os
cursos na área de informática: sistemas de informação, engenharia e ciência da computação. Atualmente estou licenciado
da PUC. Já fiz um bocado de coisas na vida, mas acho que um dos meus sonhos é um dia ser professor de matemática
para crianças: tentar despertá-las para este mundo fantástico, do qual – lastimavelmente – boa parte delas nunca chega
sequer perto ao longo de sua vida. Em 2018, comecei a dar aulas na UFPR.
9
guerra a idéia aqui é usar o computador como otimizador dos recursos bélicos, criptografia, pesquisa operacional, tabelas
balísticas...→
negócios em plena sociedade capitalista, os negócios passam a ser otimizados pelo computador. Dessa época é o COBOL
a linguagem representante... →
aldeia global Negócios, governos, universidades e organizações sociais passam a compartilhar o ciberespaço. Surge e se
robustece a Internet... →
lazer o computador vira um eletrodoméstico. As casas de classe média passam a contar com um (ou mais de um)
computador. Jogos, música, filmes, e-mule, mp3, ... →
... →
realidade virtual Não se sabe direito o que virá por aqui. As técnicas de simulação levadas ao paroxismo permitirão
criar realidades virtuais, com toda a contradição exposta no título. Talvez retornemos à dúvida de Platão (o
universo existe ou é apenas uma sensação que eu tenho?).
O computador se diferencia de qualquer outra máquina pela sua generalidade. No texto original de Turing isto fica
claro pela conceituação de uma máquina universal. Assim, diferentemente de um liquidificador (que só serve para picar
comida e tem apenas um botão de liga-desliga), um computador precisa – antes de qualquer coisa – ser programado para
fazer algo. De fato, se comprar um computador vazio e ligá-lo, ele não vai fazer nada.
Uma pergunta que se pode fazer aqui, é se é melhor aprender tudo de uma linguagem e se tornar um especialista nela,
ou se é melhor conhecer várias, ainda que não chegando a muita profundidade em nenhuma.
Não há resposta fácil, mas apostar todas as suas fichas em uma única pode ser perigoso. A tecnologia tem substituído
a linguagem “da vez” mais ou menos a cada 8, 10 anos. Pior, ao se fixar em uma linguagem, corre-se o risco de misturar
questões do problema (do algoritmo) com questões do programa (da linguagem).
Como na vida real, parece ser melhor buscar ser poliglota, ainda que obviamente haja uma linguagem preferida.
Neste caso, todo o esforço deve ser no núcleo mais ou menos comum a todas as linguagens e deixar em segundo plano o
aprendizado das idiossincrasias de cada uma.
Fica claro que programar um computador é “emprestar inteligência ao computador”. Ou seja, para programar a solução
de um problema, há que saber resolver esse problema. E, não apenas resolver em tese, mas descrever detalhadamente
todas as etapas da solução.
De fato, a programação é detalhista ao extremo.
Como se disse acima, o computador surge em 1937, descrito em um artigo denominado “on a computable numbers”.
Este artigo era tão inédito que quase não é publicado: faltavam revisores que o atestassem. O conceito matemático de
computador está lá, quase 10 anos de existir algo físico que lembrasse o conceito.
Ao mesmo tempo, o exército nazista alemão começa a usar um esquema criptográfico muito inteligente através de
uma máquina denominada ENIGMA, a qual, tinham eles certeza, era inexpugnável. Mal sabiam que do outro lado do
canal da Mancha estava Turing. Ele criou um computador, batizado COLOSSUS, que quebrava o código ENIGMA em
poucas horas. Foi o primeiro computador construído pelo homem. O ENIAC de que os americanos se gabam tanto, veio
depois.
No meio da guerra, Turing foi enviado aos Estados Unidos e lá teve contacto com Von Neumann. Este é o autor da
assim chamada arquitetura de Von Neumann, que é a que usamos até hoje em qualquer computador.
1.5 Algoritmo
Algorithms are the most important, durable, and original part of computer science because they can be studied
in a language – and machine – independent way. This means that we need techniques that enable us to compare
algorithms without implementing them.
Skiena, Steven - The Algorithm Design Manual.
A good algorithm is like a sharp knife - it does exactly what it is supposed to do with a minimum amount of
applied effort. Using the wrong algorithm to solve a problem is trying to cut a steak with a screwdriver: you
may eventually get a digestible result, but you will expend considerable more effort than necessary, and the
result is unlikely to be aesthetically pleasing.
Segundo mestre Aurélio, algoritmo é “Processo de cálculo, ou de resolução de um grupo de problemas semelhantes,
em que se estipula, com generalidade e sem restrições, regras formais para a obtenção do resultado ou da solução do
problema”.
No seu aspecto dinâmico, teríamos que gerar uma série de dados de entrada (triplas A,B,C), seguir o algoritmo, e verificar
se os resultados que ele gera são aqueles esperados de antemão.
Dado um problema, para o qual temos que escrever um algoritmo, usualmente não há solução única. Quanto mais
complexo o problema a resolver, maior a quantidade de possíveis algoritmos corretos. Cada um certamente terá as suas
qualidades e os seus defeitos. Alguns são muito bons, e outros muito ruins, mas entre um e outro existem inúmeras
variações, que nem sempre são facilmente reconhecidas.
Pode-se dizer que um algoritmo é um programa de computador do qual se faz a abstração da linguagem de programa-
ção. Neste sentido o algoritmo independe de qual será sua implementação posterior. Quando pensamos em algoritmos, não
nos preocupamos com a linguagem. Estamos querendo resolver o aspecto “conteúdo”. Mais tarde, quando programarmos,
a linguagem passa a ser importante, e agora a preocupação é com a “forma”.
Clareza O algoritmo é uma ferramenta de entendimento e solução de um problema. Deve portanto, ser o mais claro
possível. Ao fazer o algoritmo seu autor deve se preocupar constantemente em se o que está pensando está visível
no que está escrevendo.
“Nunca sacrificar clareza por eficiência; nunca sacrificar clareza pela oportunidade de revelar sua inteli-
gência.”Jean Paul Tremblay.
Impessoalidade Nem sempre quem vai examinar, depurar, corrigir, alterar etc , um algoritmo é seu autor. Portanto,
nada de usar macetes, regras pessoais, nomes que só tem sentido para o autor etc. Neste ponto é de muita
ajuda a existência de um bem organizado conjunto de normas de codificação e de elaboração de algoritmos para a
organização. As melhores e mais bem organizadas empresas de informática dedicam parcela significativa de seus
esforços a esta atividade.
“Bons comentários não podem melhorar uma má codificação, mas maus comentários podem comprometer
seriamente uma boa codificação”. Jean Paul Tremblay.
Correção (ou integridade ou ainda robustez) Um algorítmo íntegro é aquele onde os cálculos estão satisfatoria-
mente colocados, e atuam corretamente para todos os dados possíveis de entrada. Não adianta um algoritmo
sofisticado e cheio de estruturas de controle, se suas operações aritméticas elementares não estiverem corretas. É
mais comum (e perigoso) o algoritmo que funciona em 95% dos casos, mas falha em 5% deles.
Eficiência Esta característica tem a ver com economia de processamento, de memória, de comandos, de variáveis etc.
Infelizmente, quase sempre é uma característica oposta à da clareza e da simplicidade, sendo estas mais importantes
do que a eficiência. Entretanto, em alguns casos, (principalmente na programação real - dentro das empresas), a
eficiência pode ser fundamental. Neste caso, perde-se facilidade, para se ter economia. O bom programador é aquele
que alia a simplicidade ao máximo de eficiência possível.
Generalidade Dentro do possível, um algoritmo deve ser o mais genérico que puder. Isto significa que vale a pena um
esforço no sentido de deixar nossos algoritmos capazes de resolver não apenas o problema proposto, mas toda a
classe de problemas semelhantes que aparecerem. Usualmente o esforço gasto para deixar um algoritmo genérico é
pequeno em relação aos benefícios que se obtém desta preocupação.
Modularidade Algoritmos grandes dificilmente ficam bons se usarmos uma abordagem linear. É praticamente impos-
sível garantir clareza, impessoalidade, documentação etc, quando se resolve um algoritmo de cima a baixo. Uma
conveniente divisão em módulos (isto é, em sub-algoritmos), para que cada um possa ser resolvido a seu tempo.
Não podemos esquecer que a regra áurea da programação estruturada é “dividir para conquistar”.
ciclo de vida
Qual a história de vida de um programa de computador ? Isto é como nasce, cresce e morre um programa ? Grosso
modo, pode se dizer que as principais etapas são:
• estudo do problema: Espera-se que haja algum problema ou dificuldade esperando ser resolvido pelo programa de
computador. É pré-requisito antes de tentar a solução de qualquer questão, estudá-la, compreender o entorno, as
limitações, os balizadores, os recursos disponíveis. Uma boa maneira de estudar e compreender um problema é
fazer hipóteses, estudar comportamentos, projetar simulações. Só se pode passar adiante se boa parte do entorno
do problema for entendida. Note-se que nem sempre é possível aguardar até ter 100% do conhecimento antes de
seguir adiante. Às vezes não dá tempo, mas o percalço principal nem é esse: é que muitas vezes o conhecimento não
existe e só vai aparecer quando se cutucar o problema. Como se diz em espanhol los caminos se hacen al caminar.
Quando isto ocorrer, e ocorre muitas vezes, não tem jeito: anda-se para frente e para trás, e a cada passada o
conhecimento é maior.
• bolar ou procurar o algoritmo. Agora é hora de converter a solução encontrada em algo próximo a um algoritmo.
Isto é, algo formal, com condições iniciais, resultado final, e manipulações entre o que entra e o que sai. Usam-se os
comandos permitidos em algoritmos e só estes. Usualmente, há aqui o que se chama de aprofundamento interativo.
Começa-se com uma declaração genérica que vai sendo detalhada e especificada até chegar ao nível básico, no qual os
comandos algorítmicos (entrada/saída, aritméticos, alternativos, movimentação e de repetição) podem ser usados.
Note que pode-se copiar ou aproveitar um algoritmo já existente. Entretanto este re-uso dificilmente é imediato.
Sempre há que estudar e eventualmente modificar um algoritmo já existente, a menos que quando este foi feito seu
autor já tinha a preocupação com o reuso.
• transcrever em LP. É hora de escolher um computador, um ambiente operacional e sobretudo uma linguagem de
programação que esteja disponível e seja conhecida. Dessas 3 opções (computador, ambiente e linguagem) surge a
plataforma definitiva: agora é possível escrever, testar, depurar e implementar o programa de computador.
• depurar. Usualmente há uma sequência de testes:
– compilação correta: nenhum erro apresentado pelo compilador
– testes imediatos sem erro: testes ad hoc para este programa (e só para ele) dão os resultados esperados.
– teste alfa: um esforço completo de testes, inclusive integrando este programa aos seus antecessores e sucessores.
Usualmente o teste é feito pelo(s) autor(es) do programa.
– teste beta: um teste completo feito por terceiros. Há uma regra aqui de que quem faz (programador) não deve
ser quem testa (testador).
• implementar e rodar. Com o programa testado e liberado é hora de rodá-lo em produção. Nesta hora ocorre o que
tem sido chamado de deploy (dizem as más línguas que sempre associado a seu irmão gêmeo, o delay). Dependendo
do porte da instalação e do sistema, às vezes esta passagem é complexa e trabalhosa.
• manutenção. Seria muito bom se a história acabasse na etapa anterior. Não é o que ocorre, já que o mundo
muda e os programas precisam mudar com ele. Se a manutenção é pequena, usualmente pode-se fazê-la sem muito
transtorno, mas caso não seja, este ciclo recomeça. Note-se que após algumas manutenções grandes o programa
começa a dar mostrar de instabilidade –a popular colcha de retalhos – e é hora de começar tudo de novo, na nova
versão do programa.
• Tenha intimidade com algum ambiente de compilação e testes. Esta proposta é importante para poder testar
algoritmos. Se ficar embatucado diante de uma simples implementação, você terá grandes dificuldades de escrever
algoritmos.
• Escreva pequenos algoritmos. Tente fazer os exercícios (começando sempre pelos mais simples) de qualquer bom
livro de algoritmos.
• Treine a interpretação dos enunciados. Enquanto não entender o que deve ser feito, não adianta olhar para o
algoritmo, pois o motivador das ações que ele toma estará ausente. Nunca se deve começar a estudar ou a construir
um algoritmo se não houver um claro entendimento do que o algoritmo deve fazer.
Sequência simples Trata-se de um conjunto de comandos simples, que seguem um ao outro e que são executados na
ordem em que aparecem. Exemplo
A ← 10
B←A + 5
X←1 + 2
Dentro de uma sequência simples de comandos a entrada sempre é pelo primeiro comando e a saída sempre é pelo
último. Graças ao princípio da programação estruturada (uma entrada e uma saída), uma sequência simples pode ser
substituída por um bloco com entrada e saída únicas.
Alternativa ou comando condicional É um comando que permite dois caminhos alternativos, daí o nome, a depender
de alguma condição. Na matemática convencional isto já existe, por exemplo na fórmula de Bhaskhara. No momento
de calcular a raiz quadrada de ∇, há que se tomar uma decisão. Se ∇ < 0 os cálculos cessam e a resposta de raízes
imaginárias deve ser dada. Se ∇ ≥ 0, a raiz pode ser extraída e um ou dois valores de raízes emergem.
O ponto importante aqui é que em algum lugar os dois ramos se juntam novamente, e a regra de ouro da programação
estruturada (entrada única e saída única também) continua verdadeira.
Tal como na sequência, um comando alternativo, por mais complexo que seja, pode ser substituído por única caixa.
Repetição O terceiro bloco da programação estruturada é a resposta à necessidade de usar o comando de desvio.
Perceba-se que aqui existe um desvio implícito, já que ao se terminar o bloco, há que se desviar para o início do mesmo,
que é o que caracteriza uma repetição. A restrição a obedecer não é a ausência de desvio – de resto, impossível de
obedecer – mas sim a regra da entrada e saída únicas. Em outras palavras não é proibido usar o desvio, desde que ele
esteja contido em limites bem determinados.
Tal como na sequência e na alternativa, um comando de repetição, por maior ou mais complexo que seja, pode ser
substituído por única caixa.
A importância desta descoberta para o software teve tanto impacto quanto a de que qualquer forma lógica de hardware
pode ser construida pelas combinações de portas AND, OR e NOT.
A grande vantagem dos três elementos da programação estruturada é que possuem a característica de pacote ou caixa
preta, uma vez que todos tem uma única entrada e uma única saída. Isto significa que partes de programas construidos
2. o comportamento da máquina é totalmente determinado pelo seu estado interior e pelo input.
Ou seja, dado o estado inicial e um símbolo de input, o aparelho deve ser determinístico 2 . Logo ele,
• Muda o simbolo que foi lido pelo mesmo ou por outro, e/ou
Definição de uma máquina de Turing Para especificarmos nossa máquina de Turing, teríamos que escrever algo
do tipo
Estado Sinal faz Vai para Escreve Anda
atual lido o que estado para onde
0 0 → 0 0 D
0 1 → 13 1 E
1 0 → 65 1 D
1 1 → 1 0 D
2 0 → 0 1 D.PARE
2 1 → 66 1 E
Esta definição acima, é adequada para a tarefa de numeração das Máquinas de Turing, fenômeno esse que é central
na teoria. Entretanto, para operar com esta máquina, talvez seja mais adequado escrever uma tabela como
estado chega escreve? anda vai para
0 0 D 0
0 1 E 13
1 0 1 D 65
1 1 0 D 1
2 0 1 PARE
2 1 E 66
1 Eis o problema original, como proposto por Hilbert: Determination of the solvability of a diophantine equation: Given a diophantine
equation with any number of unkown quantities and with rational numerical coefficients: to devise a process according to which it can be
determined by a finite number of operations whether the equation is solvable in rational integers
2 um fenômeno é deterministico quando gera sempre o mesmo resultado a partir das mesmas condições iniciais. Por exemplo, soltar um corpo
em queda livre. Ao contrário um fenômeno probabilístico (ou randômico ou estocástico) é o fenômeno no qual dadas as mesmas condições
iniciais o resultado é imprevisível. Por exemplo, lançar um dado
101011011010010110101001110100101101011110100001110100101011
10100010111010100011010010110110101010101101010101101010100.
Convertendo este número binário para decimal chegamos a 450813704461563958982113775643437908 O que significa que a
máquina que soma 1 em unário é a 450.813.704.461.563.958.982.113.775.643.437.908a máquina de Turing. Naturalmente,
mudando-se (otimizando-se) alguma coisa na programação, esta máquina muda de número.
A máquina que soma 1 em unário é a 177.642a máquina. A que multiplica 2 em binário expandido é 10.389.728.107a
máquina e a que multiplica por 2 um número unário é a 1.492.923.420.919.872.026.917.547.669 a máquina.
E assim vai. A T7 , é não corretamente especificada, já que existem uma sequência de 5 uns, e ela emperra ao processar
tal sequência.
Máquina Universal de Turing Teremos uma máquina U, que antes de mais nada lerá as informações na fita de entrada
para que ela passe a se comportar como a máquina T. Depois disso vem os dados de input que seriam processados pela
máquina T, mas que serão pela U, operando como se fosse a T.
Dizendo que quando a n-ésima máquina de Turing atua sobre o número m produz o número p, podemos escrever
Tn (m) = p. Podemos pensar nesta relação como sendo uma função de 2 parâmetros (n e m) que leva a p. Esta função,
pelo que vimos é totalmente algoritmica. Logo, ela pode ser realizada por uma máquina de Turing, a quem chamaremos
de U . Então, fornecendo o par (n, m) a U , obtemos como resposta p.
Podemos escrever U (n, m) = Tn (m)
A máquina U quando alimentada primeiro com o número n, passa a se comportar como a Tn
Como U é uma máquina de Turing, ela é uma Talguma−coisa . Quanto é essa alguma coisa ?
É mais ou menos 7.24 × 101688 , ou seja o número 724 seguido de 1686 zeros.
Todos os computadores modernos, desde um humilde Z80 até um Cray multi-vetorial são máquinas de Turing.
Acabamos de ser apresentados a um moderno computador: em U (n, m) = p, U é o hardware, n é o software (ou
programa), m são os dados de entrada e finalmente p é o resultado esperado.
Para efeito de entender a MT, pode-se desenhar algo como segue: Usar como modelo a MT que multiplica por 2 em
unário
1. Estabelecer as regras pelas quais axiomas (e teoremas) podem gerar novos teoremas
Eis os axiomas de Peano para os números naturais. Note-se que o símbolo s denota sucessor, um conceito primitivo.
O sucessor de 0 é 1, de 1 é 2, ... de n é n+1:
Com estas informações, Gödel, passou à etapa 3 do teorema, usando a tabela a seguir:
Linguagens de programação
Humanos pensam em abstrato. Máquinas obedecem a comandos binários (bits ligados e desligados). A questão é: “como
passar de um a outro ?”. Nos primórdios da computação não havia jeito: era preciso converter do abstrato para o binário
e quem tinha que fazer isso eram os humanos.
Era tarefa difícil: os códigos binários são enfadonhos e complexos. Além do que os níveis de detalhe são exasperantes.
Claramente havia um gargalo aqui: semanas ou meses para escrever, depurar e implementar algum código mais sofisticado.
Cedo, nessa história, alguém se perguntou: porque não pôr os computadores para fazer essa delicada tradução (de
idioma abstrato e humano para os códigos elétricos e binários exigidos pelo computador) ?
Nascia o conceito de linguagem de programação. Quando se fala em LP, está-se falando de 2 coisas interligadas: de um
lado uma linguagem: suas regras de escrita, sua síntaxe e até alguma semântica. De outro lado há também um programa
de computador (certamente escrito em OUTRA linguagem) que lê comandos escritos naquela síntaxe e semântica acima
descritas e converte tais comandos em ordens que a máquina consiga obedecer. As vantagens de usar uma LP:
• É muito mais fácil aprender uma linguagem de programação do que aprender os códigos binários do computador.
A diferença de tempo de aprendizado é de horas (LP) para meses (linguagem de máquina).
• Diferentes computadores (diferentes arquiteturas) podem usar o mesmo programa escrito em uma LP, desde que
cada um tenha seu tradutor. É só olhar a lista de ambientes onde roda Python (mais de 10).
• Detalhes enfadonhos e repetitivos podem ser assumidos pelo programa tradutor liberando o humano desses detalhes.
Por exemplo, a leitura de um registro em disco exige centenas de detalhes, mas que são sempre os mesmos. Assim,
usando uma LP o programador pode comandar “leia o disco” e o tradutor se encarrega dos detalhes.
• É tentador escrever linguagens especializadas em algum domínio científico e/ou tecnológico. Mais e mais detalhes
podem ser escondidos. É o que se faz em Matlab (engenharia), Tensorflow (redes neurais), Lisp (processamento
simbólico), só para citar alguns.
• Usando este mecanismo, a humanidade passa a contar com uma ferramenta fantástica precisando investir pouco
esforço. Pode-se fazer uma analogia com dirigir um automóvel. Ninguém precisa ser mecânico ou engenheiro para
dirigir um carro. Qualquer um pode ser motorista.
1. O problema é estudado, seus algoritmos e fórmulas traduzidos e um programa é escrito. A este programa, dá-se o
nome de programa fonte.
3. O resultado é chamada programa objeto e ele agora é versão executável do programa fonte.
5. Havendo erros ou divergências (sempre as há), corrige-se o programa fonte e o ciclo recomeça.
6. Quando o resultado obtido é certificado e julgado satisfatório o programa sofre um processo chamado deployment
que significa sua entrada em regime normal de produção.
21
Neste desenho uma tentativa de explicação do processo acima descrito.
2.1 Categorias de LP
2.1.1 Quanto à geração
As gerações de software grosso modo acompanharam a idade da tecnologia. As linguagens de primeira geração nasceram
junto com o computador e foram sendo desenvolvidas a partir dos desenvolvimentos teóricos na engenharia do software.
1a geração linguagem de máquina. No máximo, um mon- ASSEMBLER
tadores
2a geração linguagens de especificação de problemas. COBOL
3a geração linguagens com jargão do problema. Mais fá- ARENA
ceis de aprender e usar.
• As antigas tem mais idiossincrasias, já que nascem em ambientes ainda pequenos sem massa crítica e com pouca
experiência. Escrever linguagens era adentrar a um mundo novo.
• As antigas tem uma obsessão com a economia de recursos. Em 1974 aprendi a programar em um computador
IBM1130 que tinha 8KB de memória. De qualquer maneira continua sendo boa idéia economizar, mas não há mais
porque gastar horas para economizar 3 bytes, por exemplo.
• As modernas agregam inúmeros recursos advindos (copiados) de ambientes bem sucedidos. Esta tendência levada
ao exagero gera linguagens que parecem Franksteins, mas há quem goste.
• Preocupação com usabilidade: esta é uma questão recente na ciência da computação, mas é bem importante.
Descobriu-se que além de se adaptar bem ao computador, uma LP deve se adaptar bem também ao cinzento.
2.3 Fortran
Fortran é uma linguagem muito antiga, originalmente sugerida pela IBM na década de 50. Seu texto se assemelha a uma
descrição matemática e de fato, FORTRAN significa FORmula TRANslation. É, ou pelo menos era, uma linguagem
franciscana de tão pobre em recursos. Foi a única linguagem ensinada em escolas de engenharia até a década de 80. O
primeiro compilador de FORTRAN foi desenvolvido para o IBM 704 em 1954-57 por uma equipe da IBM chefiada por
John W. Backus.
A inclusão de um tipo de dados de número complexo na linguagem tornou a linguagem Fortran particularmente apta
para a computação científica.
As principais revisões são a Fortran 66, 77, 90 e 95. A mais famosa e usada é a Fortran 90. Sua principal vantagem
é a eficiência em calculo numérico pesado.
A seguir, um exemplo de FORTRAN note-se que já é um Fortran revisto (e moderno): basta olhar o formato do
comando IF (antes era muito mais idiossincrático e obscuro).
C 1 2 3 4 5 6
C2345678901234567890123456789012345678901234567890123456789012345
PROGRAM BASKHARA
C
REAL A,B,C, DELTA, X1,X2, RE, IM
C
PRINT *, "Este programa resolve uma equação de 2o.grau"
PRINT *, "do tipo: a*x**2 + b*x + c = 0"
C
PRINT 10, "Digite a,b,c: "
10 FORMAT(A,1X,$)
20 READ(*,*,ERR=20) A,B,C
C
DELTA=B*B-4.*A*C
C
2.4 Lisp
LISP é a segunda linguagem de alto nivel mais antiga. O LISP nasce como filho da comunidade de Inteligência Artificial.
Na origem, 4 grupos de pessoas se inseriram na comunidade de IA: os linguistas (na busca de um tradutor universal), os
psicólogos (na tentativa de entender e estudar processos cerebrais humanos), matemáticos (a mecanização de aspectos da
matemática, por exemplo a demonstração de teoremas) e os informáticos (que buscavam expandir os limites da ciência).
O marco inicial é o encontro no Dartmouth College em 1956, que trouxe duas consequências importantes: a atribuição
do nome IA e a possibilidade dos diferentes pesquisadores se conhecerem e terem suas pesquisas beneficiadas por uma
interfecundação intelectual.
A primeira constatação foi a de que linguagens existentes privilegiavam dados numéricos na forma de arrays. Assim, a
busca foi a criação de ambientes que processassem símbolos na forma de listas. A primeira proposta foi IPL (Information
Processing Language I, por Newel e Simon em 1956). Era um assemblão com suporte a listas. A IBM engajou-se no
esforço, mas tendo gasto muito no projeto FORTRAN decidiu agregar-lhe capacidade de listas, ao invés de criar nova
linguagem. Nasceu a FLPL (Fortran List Processing Language).
Em 1958, McCarthy começou a pesquisar requisitos para uma linguagem simbólica. Foram eles: recursão, expressões
condicionais, alocação dinâmica de listas, desalocação automática. O FORTRAN não tinha a menor possibilidade de
atendê-las e assim McCarthy junto com M. Minsky desenvolveu o LISP. Buscava-se uma função Lisp Universal (como
uma máquina de Turing Universal). A primeira versão (chamada LISP pura) era completamente funcional. Mais tarde,
LISP foi sofrendo modificações e melhoramentos visando eliminar ineficiências e dificuldades de uso. Acabou por se
tornar uma linguagem 100% adequada a qualquer tipo de resolução de problema. Por exemplo, o editor EMACS que é
um padrão no mundo UNIX está feito em LISP.
Inúmeros dialetos LISP apareceram, cada um queria apresentar a sua versão como sendo a melhor. Por exemplo,
FranzLisp, ZetaLisp, LeLisp, MacLisp, Interlisp, Scheme, T, Nil, Xlisp, Autolisp etc. Finalmente, como maneira de
facilitar a comunicação entre todos estes (e outros) ambientes, trabalhou-se na criação de um padrão que foi denominado
Common Lisp. Como resultado o Common Lisp ficou grande e um tanto quanto heterogêneo, mas ele herda as melhores
práticas de cada um de seus antecessores.
Seja agora um exemplo de uma função lisp:
2.5 Prolog
O nome Prolog para a linguagem concreta foi escolhido por Philippe Roussel como uma abreviação de PROgrammation
LOGique. Foi criada em meados de 1972 por Alain Colmerauer e Philippe Roussel, baseados no conceito de Robert
Kowalski da interpretação procedimental das cláusulas de Horn. A motivação para isso veio em parte da vontade de
reconciliar o uso da lógica como uma linguagem declarativa de representação do conhecimento com a representação
procedimental do conhecimento.
A seguir um histórico de Prolog:
• Robinson, 65, no artigo A machine oriented logic based on the resolution principle. Propunha o uso da fórmula
clausal, do uso de resolução e principalmente do algoritmo de unificação.
• Green em 1969, escreveu o Question Answer System, que respondia perguntas sobre um dado domínio. Na mesma
época, Winograd escreveu o software Planner.
• Todos estes tinham problemas de eficiência, por causa, entre outras coisas, da explosão combinatória.
• Em 77, Waren escreve o primeiro compilador de PROLOG. Começa o sucesso de PROLOG na Europa. Nos EUA,
sempre deu-se maior atenção ao LISP.
parent(maria,jorge):-true.
parent(joao,jorge):-true.
parent(jorge,ana):-true.
...
parent(cris,paulo):-true.
? parent(joao,jorge)
YES
? parent(celia,cris)
NO
? parent(cris,carlos)
NO
? parent(X,jorge)
X=maria
X=joao
no (significando acabou)
? parent(X,Y)
X=maria
Y=jorge
X=joao
Y=jorge
...
? parent(X,Y),parent(Y,paulo) [ler esta vírgula como OU]
X=jorge
Y=cris
2.6 Cobol
O nome vem da sigla de COmmon Business Oriented Language (Linguagem Comum Orientada aos Negócios), que define
seu objetivo principal em sistemas comerciais, financeiros e administrativos para empresas e governos.
O COBOL foi criado em 1959 pelo Comitê de Curto Prazo, um dos três comitês propostos numa reunião no Pentágono
em Maio de 1959, organizado por Charles Phillips do Departamento de Defesa dos Estados Unidos. O Comitê de
Curto Prazo foi formado para recomendar as diretrizes de uma linguagem para negócios. Foi constituído por membros
representantes de seis fabricantes de computadores e três órgãos governamentais, a saber: Burroughs Corporation, IBM,
Minneapolis-Honeywell (Honeywell Labs), RCA, Sperry Rand, e Sylvania Electric Products, e a Força Aérea dos Estados
Unidos, o David Taylor Model Basin e a Agência Nacional de Padrões (National Bureau of Standards ou NBS). Este
comitê foi presidido por um membro do NBS. Um comitê de Médio Prazo e outro de Longo Prazo foram também propostos
na reunião do Pentágono. Entretanto, embora tenha sido formado, o Comitê de Médio Prazo nunca chegou a funcionar;
2.7 APL
Ela nasceu do trabalho de um professor de matemática canadense de nome Keneth Iverson. Sua proposta original era a
de produzir uma nova notação matemática, menos sujeita às ambiguidades da notação convencional.
Na década de 60, trabalhando na IBM em conjunto com Adin Falcoff, ambos produziram a primeira versão de APL,
quando um interpretador da linguagem ficou disponível.
A principal característica de APL é o uso de um conjunto especial de caracteres que incluem algumas letras gregas
(rho, iota...), símbolos matemáticos convencionais (o sinal de vezes, o de dividido...) e alguns símbolos especialmente
inventados.
Este fato sempre limitou a disseminação da linguagem. Até o advento das interfaces gráficas, como o windows, por
exemplo, exigia-se um hardware especial para poder programar em APL.
Programas em APL em geral sempre são muito pequenos, embora poderosos. A linguagem está preparada para tratar
arranjos de grandes dimensões. Por exemplo, quando em APL se escreve A+B, se A e B forem escalares (isto é um
número único), a resposta também o será. Se A e B são vetores de 100 números, a resposta também o será. Idem para
matrizes e até arrays-nd. Em algumas versões de APL este n chega a 256 dimensões.
Este é um comando EDIT (troca algo, de... para...)
∇edit[⎕]∇
∇
[0] r←depara edit x
[1] r←,x
[2] r[(r=1↑depara)/⍳⍴r]←1↓depara
[3] r←(⍴x)⍴r
∇ 2018-06-24 10.03.49 (GMT-4)
x←3 3⍴?9⍴4
x
2 1 3
1 3 3
2 2 2
2 99 edit x
99 1 3
1 3 3
99 99 99
2.8 Basic
A linguagem BASIC (acrônimo para Beginners All-purpose Symbolic Instruction Code), foi criada, com fins didáticos,
pelos professores John G. Kemeny e T. Kurtz em 1963 no Dartmouth College.
O programa demonstra a falta de estruturação da linguagem original, pois o IF funciona como um GOTO condicional, o
que favorece o código espaguete.
2.9 Clipper
Tudo começou com o dbase, que foi o precursor de bancos de dados para micros. Por volta de 83, 84 surgiu o dbase 2
(nunca houve o 1) para micros de 8 bits com memórias típicas de 64Kb e um ou dois disquetes de 8 polegadas e cerca de
512 KB de capacidade em cada um.
O dbase já era um gerenciador de dados, dentro da visão relacional, com mínima redundância de dados e com todas
as garantias de acesso e uma linguagem estruturada, no melhor padrão, de uso geral, capaz de garantir um aumento na
produtividade na programação.
A história do dBASE começa em 74, no Jet Propulsion Laboratory, conhecido como JPL, e instalado em Pasadena,
Califórnia.
Nesta instalação da NASA trabalhava Jeb Long, pesquisador que lidava com dados obtidos nas pesquisas espaciais
através de naves não tripuladas. Estes, por serem em grande número, começaram a trazer problemas e dissabores a Jeb
Long, que desenvolveu, então, um programa de computador capaz de gerenciar tais informações. Este programa com
nome de JPLDIS, foi concluído e alcançou razoável sucesso tendo sido bastante comentado pelo pessoal técnico. Foi o que
bastou para que um analista de sistemas (Wayne Ratliff) começasse a desenvolver um programa gerenciador de dados,
genérico, mas tendo como modelo o JPLDIS.
Rapidamente o novo trabalho tornou-se melhor do que o original, e Ratliff desenvolveu-o cada vez mais.
Em 79, Ratliff achou que o programa já estava maduro e pronto para enfrentar o mercado, e ele foi anunciado com o
nome de VULCAN. Foi, entretanto, um fracasso: não se chegou a vender sequer 50 cópias.
Alguns meses depois, um grande distribuidor de programas de micros, George Tate, tomou conhecimento do dBASE.
Testou-o e ficou entusiasmado.
Achou que o que faltava a Ratliff era suporte comercial, uma vez que seu trabalho era muito bom. Rapidamente
providenciaram-se algumas mudanças cosméticas no programa, seu nome foi mudado para dBASE II (nunca houve o
dBASE I, tratava-se de estratégia comercial, para apresentar o produto como um melhoramento), e uma nova empresa
(ASHTON TATE) foi criada para vender este produto.
Em pouco tempo, dBASE tornou-se um marco na história de softwares para microcomputadores.
A grande vantagem de um banco de dados é retirar a amarração entre programas e dados.
A explicação desta vantagem é que dados são muito mais estáveis do que os procedimentos (=programas). Separando-
os garante-se que longevidade aos dados, que em geral são os mais custosos para adquirir.
O dbase como linguagem era interpretado, o que trazia desempenho pífio nas aplicações, além da eventual falta de se-
gurança (qualquer um podia alterar os dados). Para corrigir estas duas deficiências, logo surgiram inúmeros compiladores,
dos quais o mais famoso foi o CLIPPER.
Eis um programa em CLIPPER, por acaso um trecho do programa que emite provas aleatórias e diferentes:
2.10 Natural
NATURAL é uma linguagem de quarta geração que pode ser utilizada, indistintamente por usuários finais trabalhando
em auto-serviço, ou por programadores profissionais em suas atividades normais no CPD.
Embora possa ler arquivos sequenciais, o Natural é mais indicado para ler bancos de dados ADABAS, que a partir
da década de 90 foi o padrão de bancos de dados em nosso país e em boa parte do mundo.
Eis um exemplo de programa em Natural:
2.11 Pascal
É uma linguagem de programação estruturada que recebeu este nome em homenagem ao matemático Blaise Pascal. Foi
criada em 1970 pelo suíço Niklaus Wirth, tendo em mente encorajar o uso de código estruturado.
Segundo o autor, Pascal foi criada simultaneamente para ensinar programação estruturada e para ser utilizada em
sua fábrica de software. A linguagem reflete a liberação pessoal de Wirth após seu envolvimento com a especificação de
ALGOL 68, e sua sugestão para essa especificação, o ALGOL W.
A linguagem é extremamente bem estruturada e muito adequada para ensino de linguagens de programação. É
provavelmente uma das linguagens mais bem resolvidas entre as linguagens estruturadas, e certamente um dos exemplos
de como uma linguagem especificada por uma pessoa pode ser bem melhor do que uma linguagem especificada por um
comitê.
Pascal originou uma enorme gama de dialetos, podendo também ser considerada uma família de linguagens de pro-
gramação. Grande parte de seu sucesso se deve a criação, na década de 80, da linguagem Turbo Pascal, inicialmente
disponível para computadores baseados na na arquitetura 8086 (com versões para 8080 no seu início).
Pascal é normalmente uma das linguagens de escolha para ensinar programação, junto com Scheme, C e Fortran. Só
mais recentemente o Java entrou nesta lista.
Comercialmente, a linguagem foi sucedida pela criação da linguagem Object Pascal, atualmente utilizada nas IDEs
Borland Delphi, Kylix e Lazarus. Academicamente, seus sucessores são as linguagens subsequentes de Niklaus Wirth:
Modula-2 e Oberon.
A partir da versão 2005, o Delphi passou a se referir a sua linguagem de programação como Delphi Language.
2.12 C
C é uma linguagem de programação estruturada e padronizada criada na década de 1970 por Dennis Ritchie e Ken
Thompson para ser usada no sistema operacional UNIX. Desde então espalhou-se por muitos outros sistemas operacionais,
e tornou-se uma das linguagens de programação mais usadas.
C tem como ponto-forte a sua eficiência e é a linguagem de programação de preferência para o desenvolvimento de
software básico, apesar de também ser usada para desenvolver aplicações. É também muito usada no ensino de ciências
da computação, mesmo não tendo sido projetada para estudantes e apresentando algumas dificuldades no seu uso. Outra
característica importante de C é sua proximidade com a linguagem de máquina, que permite que um projetista seja capaz
de fazer algumas previsões de como o software irá se comportar ao ser executado.
C tem como ponto fraco a falta de proteção que dá ao programador. Praticamente tudo que se expressa em um
programa em C pode ser executado, como por exemplo pedir o vigésimo membro de um vetor com apenas dez membros.
Os resultados muitas vezes totalmente inesperados e os erros são difíceis de encontrar.
Muitas linguagens de programação foram influenciadas por C, sendo que a mais utilizada atualmente é C++, que por
sua vez foi uma das inspirações para Java. O exemplo:
#include <stdio.h>
struct pessoa
{
unsigned short idade;
char nome[51]; /*vector de 51 chars para o nome*/
unsigned long bi;
}; /*estrutura declarada*/
int main(void) {
struct pessoa Sousa={16,"Diogo Sousa",123456789};
/*declaracao de uma variavel tipo struct
pessoa com o nome Sousa*/
printf("Idade: %d\n",(int)Sousa.idade); /* "%d" espera um int */
printf("Nome: %s\n",Sousa.nome);
printf("BI: %lu\n",Sousa.bi);
return 0;
}
2.13 C++
C++ é uma extensão da linguagem C, corrigindo algumas de suas deficências originais (como por exemplo, a incapa-
cidade de C de generalizar o tipo de dado em uma estrutura particular), além de incluir a manipulação de objetos e a
simplificação de algumas tarefas (como entrada/saída padrão, por exemplo). Mas, C++ se saiu muito bem por herdar
uma compatibilidade com o legado. (Um programa fonte C já é um programa fonte C++). Essa idéia transformou o
conjunto C/C++ no grande campeão de uso no mundo da informática. O TIOBE (www.tiobe.com) de junho de 2018
apresenta os seguintes valores de uso no mundo: java com 15.5%, C com 14.9%, c++ com 8.3% e python com 5.7%. Se
somarmos c com c++ o resultado é 23.2%, e esse conjunto se sagra campeão da lista. A seguir, o mesmo programa feito
em C e em C++. Compare e tire suas conclusões
#include<stdio.h>
int main(){
#include<iostream>
void main(){
long long a,b,c;
while (cin>>a>>b){
if(b>a)
c=b-a;
else
c=a-b.
cout<<c<<endl;
}
}
2.14 Java
Java é uma linguagem de programação orientada a objeto desenvolvida na década de 90 pelo programador James Gosling,
na empresa Sun Microsystems. Diferentemente das linguagens convencionais, que são compiladas para código nativo, a
linguagem Java é compilada para um ”bytecode” que é executado por uma máquina virtual.
Desde seu lançamento, em maio de 1995, a plataforma Java foi adotada mais rapidamente do que qualquer outra
linguagem de programação na história da computação. Em 2003 Java atingiu a marca de 4 milhões de desenvolvedores
em todo mundo. Java continuou crescendo e hoje é uma referência no mercado de desenvolvimento de software. Java
tornou-se popular pelo seu uso na Internet e hoje possui seu ambiente de execução presente em web browsers, mainframes,
SOs, celulares, palmtops e cartões inteligentes, entre outros.
Principais Características da Linguagem Java
A linguagem Java foi projetada tendo em vista os seguintes objetivos:
Orientação a objeto - Baseado no modelo de Smalltalk e Simula67
Portabilidade - Independência de plataforma - “write once run anywhere”
Recursos de Rede - Possui extensa biblioteca de rotinas que facilitam a cooperação com protocolos TCP/IP, como HTTP
e FTP
Segurança - Pode executar programas via rede com restrições de execução
Sintaxe similar a Linguagem C/C++
Facilidades de Internacionalização - Suporta nativamente caracteres Unicode
Simplicidade na especificação, tanto da linguagem como do ”ambiente”de execução (JVM)
É distribuída com um vasto conjunto de bibliotecas (ou APIs)
Possui facilidades para criação de programas distribuídos e multitarefa (múltiplas linhas de execução num mesmo pro-
grama)
Desalocação de memória automática por processo de coletor de lixo (garbage collector)
Carga Dinâmica de Código - Programas em Java são formados por uma coleção de classes armazenadas independente-
mente e que podem ser carregadas no momento de utilização.
Eis um exemplo:
2.15 PHP
PHP (um acrônimo recursivo para “PHP: Hypertext Preprocessor”) uma linguagem de programação de computadores
interpretada, livre e muito utilizada para gerar conteúdo dinâmico na Web.
A linguagem surgiu por volta de 1994, como um subconjunto de scripts Perl criados por Rasmus Lerdof, com o nome
Personal Home Page Tools. Mais tarde, em 1997, foi lançado o novo pacote da linguagem com o nome de PHP/FI,
trazendo a ferramenta Forms Interpreter, que era na verdade um interpretador de comandos SQL.
Trata-se de uma linguagem modularizada, o que a torna ideal para instalação e uso em servidores web. Diversos
módulos são criados no repositório de extensões PECL (PHP Extension Community Library) e alguns destes módulos
são introduzidos como padrão em novas versões da linguagem. Muito parecida, em tipos de dados, sintaxe e mesmo
funções, com a linguagem C e com a C++. Pode ser, dependendo da configuração do servidor, embutida no código
HTML. Existem versões do PHP disponíveis para os seguintes sistemas operacionais: Windows, Linux, FreeBSD, Mac
OS, OS/2, AS/400, Novell Netware, RISC OS, IRIX e Solaris
Construir uma página dinâmica baseada em bases de dados é simples, com PHP. Este provê suporte a um grande
número de bases de dados: Oracle, Sybase, PostgreSQL, InterBase, MySQL, SQLite, MSSQL, Firebird etc, podendo
abstrair o banco com a biblioteca ADOdb, entre outras.
PHP tem suporte aos protocolos: IMAP, SNMP, NNTP, POP3, HTTP, LDAP, XML-RPC, SOAP. É possível abrir
sockets e interagir com outros protocolos. E as bibliotecas de terceiros expandem ainda mais estas funcionalidades.
Veja um exemplo de PHP
<? ...
$tipss =mysql_result($result,0,'SSERVTIPSS');
$porss =mysql_result($result,0,'SSERVPORSS');
$daali =mysql_result($result,0,'SSERVDAALI');
$anexo =mysql_result($result,0,'SSERVANEXO');
$query = "select * from ANDAM where ANDAMNSERV ='$nserv1' " ;
$result = mysql_query($query);
$quantos = mysql_num_rows($result);
$quantos++;
?>
<table > <tr>
<td>Numero da solicitacao de servico<td><? echo $nserv ?><tr>
<td>autor<td><? echo $nomeu ?><tr>
<td>cliente<td><? echo $clien ?><tr>
<td>CA responsavel<td><? echo $cares ?><tr>
<td>interlocutor no cliente<td><? echo $intcl ?><tr>
<td>fone<td><? echo $fonic ?><tr>
<td>email<td><? echo $emaic ?><tr>
2.16 J
Para os que acharam APL uma linguagem meio sem pés nem cabeça, eis aqui J. Olhando para o J, o APL passa a ser
tão comportada quanto um COBOL da década de 70.
Para entender o J, precisamos estudar a vida do cara que inventou o APL, o canadense Ken Iverson. Na minha opinião,
o sujeito foi um gênio. Coloco-o sem nenhum medo de errar na galeria dos grandes matemáticos da humanidade, talvez
o primeiro (junto com Mandelbroot) que tenha realmente conseguido casar com sucesso a matemática e a computação.
Depois de propor o APL como uma notação matemática (década de 50), de liderar o grupo que converteu o APL em
linguagem de programação (década de 60 na IBM) e de liderar a popularização da linguagem (anos 70 e começos dos 80),
em meados dos 80, ele chegou a algumas conclusões:
• o uso de um alfabeto não usual (para ser educado), restringia o uso do APL (lembremos que ainda não havia o
windows e portanto para usar APL havia que comprar hardware especializado - e caro).
• o desenvolvimento continuado por 30 anos da linguagem apontou algumas inconsistências teóricas no modelo. Não
esqueçamos que o Iverson era um matemático da pesada
• o custo que o APL sempre teve inviabilizava seu uso pelos menos aquinhoados
Equivale ao programa gerasima do workspace vivo128, que gera um sistema de n incógnitas e n equações, depois o resolve
para obter os termos independentes e possibilitar propor ao aluno que descubra as incógnitas.
2.17 Lua
Lua é inteiramente projetada, implementada e desenvolvida no Brasil, por uma equipe na PUC-Rio (Pontifícia Universi-
dade Católica do Rio de Janeiro). Lua nasceu e cresceu no Tecgraf, o Grupo de Tecnologia em Computação Gráfica da
PUC-Rio. Atualmente, Lua é desenvolvida no laboratório Lablua. Tanto o Tecgraf quanto Lablua são laboratórios do
Departamento de Informática da PUC-Rio. É, ao que eu saiba, a única iniciativa brasileira na área de linguagens a obter
alguma aceitação mundial.
O projeto e a evolução de Lua foram apresentados em junho de 2007 na HOPL III, a 3a Conferência da ACM sobre
a História das Linguagens de Programação. Essa conferência ocorre a cada 15 anos (a primeira foi em 1978 e a segunda
em 1993) e somente poucas linguagens são apresentadas a cada vez. A escolha de Lua para a HOPL III é um importante
reconhecimento do seu impacto mundial. Lua é a única linguagem de programação de impacto desenvolvida fora do
primeiro mundo, estando atualmente entre as 20 linguagens mais populares na Internet (segundo o índice TIOBE).
(Dados obtidos em www.lua.org)
Eis um exemplo de lua
function fatorial(n)
if n < 2 then
return 1
else
return n * fatorial(n-1)
end
end
function exemplo()
print("Ola mundo\n\n")
print("Tchau......\n")
end
-- execução da função
exemplo()
Python
• É uma linguagem moderna (nasceu em 1990) e herdou tudo de bom que as demais linguagens já tinham nessa
época. Uma coisa que ela não herdou foi a preocupação exigente de desempenho: Em 90, já havia computação
abundante. Com isso a linguagem é redonda e não impõe trancos e barrancos para funcionar. 1
• Multiplataforma: Unix, Windows, Apple, celular android, raspberry e outros ambientes menos famosos rodam
exatamente o mesmo programa.
• Freeware: pode copiar, baixar, instalar, vender, ceder... pode fazer qualquer coisa sem infringir a lei e sem dever
explicações a ninguém.
• Uso no mainstream: Olhem o que diz o Philip Guo, um blogueiro da CACM ”oito dos top-10 Departamentos de
Ciência da Computação e 27 dos top-39 Departamentos de Ciência da Computação das principais universidades nos
EUA usam Python nos cursos introdutórios de CS0 e CS1” (CS0 e CS1 são os cursos introdutórios de Computer
Science lá). As 39 universidades pesquisadas por ele incluem: MIT, Berkeley, Stanford, Un. Columbia, UCLA,
UIUC, Cornell, Caltech, Un. Michigan, Carnegie Mellon, entre outras 2
• Muito Usada: o índice TIOBE 3 lista o Python como a quinta linguagem mais usada no mundo em 2017. . Em
junho de 2018, Python já é a quarta linguagem mais usada. Perde apenas para java, c e c++. E, corre por fora...
Se você olhar o estudo da TIOBE https://www.tiobe.com/tiobe-index/ verá o bonito papel desempenhado
pelo Python.
Linguagem 17 12 07 02 97 92
Java 1 1 1 1 12 -
C 2 2 2 2 1 1
C++ 3 3 3 3 2 2
C# 4 4 7 17 - -
Python 5 7 6 11 27 -
VB.NET 6 19 - - - -
PHP 7 6 4 5 - -
JavaScript 8 9 8 8 19 -
COBOL 25 28 17 9 3 10
Lisp 32 12 14 12 9 5
Prolog 33 32 26 15 20 12
Pascal 106 15 19 97 8 3
Consulta em 07/2017
Uma pequena explicação desta tabela: ela lista de 5 em 5 anos (o que no mundo da computação é quase uma
eternidade) a lista dos top-10 ou as linguagens de programação mais usadas. O começo é 1992, e daí de 5 em 5
anos, por 30 anos ou 6 ciclos, até o último em 2017. Diversos fenômenos podem ser observados, eis alguns:
– A performance notável de Java, cuja explicação parece estar na palavra portabilidade ou seja o mesmo programa
fonte rodando em inúmeras plataformas distintas. Isso é conseguido pelo conceito de java machine. Foge ao
1 Em compensação, quando se organiza uma maratona de programação, para um determinado problema, impõe-se 1 segundo de CPU quando
ele é resolvido em C++ e pelo menos 10 (10 vezes mais) para quando ele é resolvido usando Python
2 https://cacm.acm.org/ blogs/blog-cacm/176450 -pyhon-is-now-the -most-popular-introductory- teaching-language-at- top-u-s-universities/
35
escopo deste texto descrever o conceito, mais em resumo é uma capa ou camada de compatibilidade que se
adiciona ao ambiente de maneira a tornar ou permitir a mesma coisa sobre coisas diferentes.
– A derrocada do Pascal, nascido como uma execelente ferramenta de aprendizado e que em algum momento se
perde completamente.
– A consistência de C e seus agregados (c++ e c#), seu sucesso pode ser descrito como eficiência e o possível
alto nível de portabilidade.
– A morte anunciada e posteriormente executada do COBOL. Ele só permanece com alguma relevância graças
ao legado ou aos milhões de linha de código que ainda precisam ser mantidos vivos.
– Quase a mesma coisa pode ser dita das linguagens da inteligência artificial: Lisp e Prolog. Elas migram para
a generalidade: Java, C e Python.
– A irrupção da Internet: PHP, Javascript e Python, por trás dos panos. Inclusive da Internet das Coisas (aqui
com Java).
• Pacotes, pacotes, pacotes. A comunidade Python mantém o PYPI (Python Package Index) que é um repositório
freeware com pacotes de programação: hoje ele tem mais de 110.000 pacotes. Só para ter uma idéia, um pacote
destes, o NUMPY (numerical computation in Python) tem um manual de referência de mais de 1500 páginas.
• Inteligência Artificial: Quando o Google resolveu aposentar o DistBelief e criar uma nova ferramenta de Machine
Learning, escolheu a linguagem Python para desenvolvê-la: nasceu o Tensor Flow, que está por trás de inúmeras
iniciativas google: tradução, classificação de imagens, elaboração de perfis etc. 4 Logo na entrada do produto
o aviso: pode usar em Java, C++ ou Go. Mas, se quiser usar a funcionalidade completa do produto, use-o em
Python, que ele está feito nessa linguagem.
• Fácil: parece portugol, ou vá lá: inglêsgol. Não tem caracteres sobrando: sem ponto e vírgula, sem chaves nem
colchetes. O que se escreve, ele executa e raramente dá erro.
4 www.tensorflow.org
Python é freeware, não custa nada, você pode copiar e usar para o que desejar, sem pedir licença a ninguém, e pode
inclusive cobrar pelo software que você desenvolver usando Python. A partícula free em freeware significa liberdade para
fazer o que você quiser sem nenhum tipo de restrição e não gratuidade, como alguns pensam.
Existem versões de Python para quase todos os sistemas operacionais conhecidos, eis alguns: AIX (da IBM), AROS
(Amiga), AS/400, HPUnix, Linux, MacOS, MS-DOS, OS/2, PalmOS, Playstation, Solaris, VMS, Windows (32 e 64),
WindowsCE, entre outros.
Esta multiplicidade de versões acrescenta uma qualidade imensa aos programas Python: desde que eles não usem
nenhum recurso específico de uma dessas arquiteturas, serão 100% (ou quase isso) portáveis podendo rodar o mesmo
programa em todas essas plataformas.
4.1 Versão
As versões de Python são numeradas em 3 níveis: O primeiro número identifica a versão global que atualmente pode ser
2 ou 3. Além das versões 0 e 1, quase experimentais, a linguagem começou sua carreira global com a versão 2, que chegou
a ser bastante usada, muito software foi construído com ela, e esse fato impede agora que ela seja totalmente substituída
pela versão 3, o que seria o melhor dos mundos. Se você está começando agora, não há o que pensar: deve-se escolher a
versão 3. O problema é que na mudança de 2 para 3 perdeu-se alguma compatibilidade o que impede a livre transição
de uma a outra. A versão 2 já está com sua sentença de morte estabelecida, ela só será suportada até 2020. Desse ponto
em diante quem quiser usá-la o fará por sua conta e risco.
O segundo número indica a sub-versão, que diferencia algum nível maior de correção e sobretudo de lançamento de
novidades. Finalmente o terceiro número vai sendo incrementado à medida em que pequenas correções e melhoramentos
vão sendo construídos. Eis uma pequena versão das modificações:
Existe tamanha diversidade no mundo Python que é impossível tratar todas as alternativas de uso. Primeiro, vai-se
escolher o Python 3 e depois vai-se olhar 3 delas: a mais tradicional possível, sob Windows (nas 2 versões, sob 32 e sob
64 bits) e também uma instalação alternativa que permite instalar o Python em um pendrive para usá-lo em qualquer
computador, mesmo sem os direitos de administrador nesse computador e o Python interativo.
37
Daí, deve-se ir a https://www.python.org/downloads/ e escolher a última versão de distribuição. Usualmente
há versões mais novas que a última, mas são conhecidas como experimentais e não são recomendáveis, pois ainda não
estão cristalizadas ou consolidadas. Deve-se escolher sempre o Python 3 e não o 2, que este vai desaparecer nos próximos
anos e só está nessa lista para quem precisa usar e suportar software antigo.
No processo de instalação, especial preocupação deve ser tida ao verificar em qual diretório a instalação vai ser feita.
Eu recomendo criar um diretório novo (não usar a sugestão do instalador) no primeiro nível, logo abaixo do nível raiz
(como em c:/python3). Sob este diretório, o instalador vai criar diversos sub-diretórios (DLL, doc, etc, include, LIB,
libs, Scripts, tcl e tools). É importante olhar isto, pois para instalar novos pacotes é preciso entrar no diretório Scripts,
como se verá adiante. Logo é preciso saber onde está.
Depois de instalar o Python, deverá aparecer no seu menu inicial um ícone com 2 cobrinhas (uma azul e outra amarela)
o desenho padrão do Python. O nome deve identificar qual a versão instalada e quando se clicar nele deve-se abrir
uma tela inicial do python, como em
Nessa tela minimalista, surgem algumas informações como versão, data e hora da liberação desta versão, tipo de
sistema sob qual ela está rodando. Depois algumas opções disponíveis e finalmente o símbolo
>>>
Ele é o prompt (prontidão) que é um conceito usado por praticamente todos os softwares interativos para sinalizar ao
operador que o software está pronto para aceitar e executar comandos. Enquanto este símbolo não aparecer, isso significa
que o processador está ocupado fazendo alguma coisa e não pode ser interrompido pelo operador.
Aqui já se podem escrever comandos Python como em
>>> 1+2
3
>>>
Aqui pediu-se ao Python a execução de 1 + 2 e ele respondeu 3, seguido de um novo prompt. Esta modalidade de uso do
Python e conhecida como interativa e neste caso ele funciona como se fosse uma calculadora. Basta comandar alguma
coisa e ele a executará.
2. no menu que vai aparecer, escolha New File e lembre que estes dois passos podem ser comandados apertando
Ctrl N
3. Vai-se abrir uma nova tela em branco, muito parecida com a tela do Python. Parece Python, mas não é Python e
sim o bloco de notas do Python1
print("alo mundo")
1 Uma maneira enviezada de identificar qual tela é qual é esta: o bloco de notas do python tem o comando Run enquanto a tela do Python
não tem este comando.
Esta tela mostra a execução do script que você criou e a mensagem sendo mostrada.
8. Isto significa que você teve sucesso na instalação do python e na criação e execução do seu primeiro programa.
4.4 Winpython
Esta implementação aparece aqui por algumas razões, sendo a principal a portabilidade do ambiente de desenvolvimento:
• Permite usar Python em máquinas nas quais você não é o administrador, coisa que o Python padrão exige para ser
instalado.
• Como consequência, este Python é portável, e pode ser carregado em um pendrive ou similar, ainda que haja alguma
demora no processo de carga: o winpython é enorme.
• Winpython é um ambiente científico, pelo que já vem com SciPi e Numpy devidamente instalados, além de even-
tualmente outros pacotes importantes.
4.5 Ipython
É um python interativo, no qual fica mais evidente o diálogo entre usuário e Python. Na sua versão original (Python) é
uma linguagem de programação que conta com um enfoque interativo também. No Ipython, ao contrário, é um ambiente
interativo, que por acaso também dá acesso a uma linguagem de programação.
Ele aperece aqui nesta lista pois é a versão disponibilizada nos laboratórios do curso de engenharia elétrica da UFPR.
Neste ambiente, eis o caminho das pedras:
1. Usar seu login para entrar no sistema.
2. Na tela de atividades, digitar IP e aguardar. Escolher Ipython.
3. Carregar também o editor GEDIT. Manter ambos abertos. (Ipython e GEDIT)
4. Escrever o código python no GEDIT e salvar o programa e sua execução no diretório /eletrica, com o nome de
aa.py
5. Dentro do Ipython executar %run aa.py
6. Para corrigir, edite no GEDIT, salve e reexecute dentro do Ipython.
Uma variável é um objeto do mundo do software que pode ter algumas abordagens. A primeira, é aquela da matemática,
quando se escreve y = f (x) e se quer dizer que y é uma variável que depende do valor de x. O que existe aí, nessa
expressão, é uma função que associa o valor de y ao valor de x. Tanto x quanto y nesse enfoque são variáveis: isto é são
valores eventualmente desconhecidos, mas que têm um valor qualquer. Outra abordagem é da ciência da computação:
nela, uma variável é um pedacinho de memória dentro de um programa (que está devidamente registrado nessa memória)
e que armazena um determinado valor. Cada variável precisa ter um nome, para que possa ser referenciada. Esse nome
precisa ser único (não se pode ter duas variáveis com o mesmo nome), e depois que ela foi criada, usar essa variável num
comando qualquer é exatamente a mesma coisa que usar o valor que a variável tem. Por exemplo, se a variável A tem o
valor 10, tanto faz escrever A + 1 como 10 + 1, só que no primeiro caso, a generalidade é maior, pois independentemente
do valor que ela tiver, depois de executar A + 1, ter-se-á um valor uma unidade maior do que o valor anterior de A.
5.1 Atribuição
O comando importante aqui é o chamado atribuição . É ele que permite:
As duas funções só se diferenciam pelo existência prévia da variável. Se ela não existe, usar a atribuição significa criar a
variável. Se ela já existia (e portanto tinha um valor qualquer) usar a atribuição nela vai alterar o valor dela para este,
que é citado agora na atribuição.
O formato do comando é
variável = valor
Onde variável é o nome da variável, = identifica o comando de atribuição e valor é o valor que a variável passará a
ter depois desta atribuição. Por exemplo:
A=10 A variável de nome A é criada (ou alterada) e passa a ter o valor 10.
X=-33.4 Agora o valor de X é o número negativo -33.4
NM='alfa' A variável agora se chama NM e seu valor é uma palavra, que é ’alfa’. Atente para a presença das aspas, elas ser
Algumas observações importantes. O caráter de atribuição é = e ele é lido como recebe. Então, o comando A = 10
deve ser lido como A recebe 10. Outra observação é que este sinal tem outras funções no mundo. Por exemplo, na
matemática o sinal de igual é isso mesmo: para indicar uma igualdade. Igualdade não é a mesma coisa que atribuição.
O problema é que se não se usar o igual, que outro símbolo pode-se usar ? Outras linguagens resolveram esse problema,
usando dois caracteres (por exemplo, Pascal usa :=) enquanto outras usaram caracteres novos, como por exemplo APL,
que usa ←.
A discussão de qual símbolo usar para a atribuição (que lembrando é um conceito que não existe na mátemática) é
antiga e poderia ser aberta aqui. Mas, pegando carona no C, linguagem avô de boa parte do leque de linguagens usadas
no século XXI, (tais como C++, Java, PHP, entre outras), o Python também associou o sinal de = à atribuição. A
pergunta é: o que usar quando se falar sobre igualdade entre dois valores ? Neste caso, usam-se 2 caracteres iguais.
Então, para perguntar se as variáveis A e B têm o mesmo valor, escreve-se A == B, já que se se escrever A = B, o que
se estará mandando fazer é atribuir o valor da variável B para a variável A.
Voltando ao formato do comando de atribuição, acima descrito, vamos estudar o que pode ser valor citado no
formato do comando. Como o nome sugere, valor pode ser um número como 13, 2780.4, -33 e assim por diante. Mas,
também pode ser outra variável, como em A=X. Aqui se está mandando copiar o valor de X para a variável A. Note que
não se sabe que valor é esse. Não importa, ele é copiado de X para A.
41
Finalmente, esse valor pode ser uma expressão aritmética como em A=11+8, ou em A=V-3, ou finalmente A=cos(theta).
No primeiro caso, A vale 19, no segundo vale o valor de V menos 3 e no terceiro caso A vale o coseno do angulo theta.
Agora pode-se ver a importância da presença das aspas no comando de atribuição: acompanhe no exemplo A='alfa'
e A=alfa. No primeiro caso, é o conteúdo alfa que está sendo atribuído à variável A. No segundo pressupõe-se a
existência de uma variável de nome alfa e é esta variável que tem seu valor (seja ele qual for) copiado para a variável A.
As aspas denotam um conteúdo alfanumérico, que estruturalmente é diferente de um conteúdo puramente numérico.
Há muitas diferenças que ainda serão estudadas, mas uma importante é que conteúdos (e variáveis) numéricas podem ser
usadas em expressões aritméticas enquanto variáveis alfanuméricas causam erros de execução quando se tenta envolvê-las
em expressões numérico-aritméticas.
O erro é sinalizado pela mensagem TypeError: unsupported operand type(s) for +: 'float' and 'str'
cuja tradução é: Erro de tipo: não se pode somar (+) um tipo float com um tipo str.
Múltiplo assinalamento
Pode-se atribuir o mesmo valor a diversas variáveis:
a=b=c=d=0
Neste caso, foram criadas (alteradas) as variáveis a, b, c e d todas com o valor zero.
>>> a,b,c=5.6,0,'alfa'
>>> a
5.6
>>> b
0
>>> c
'alfa'
Note que a quantidade de variáveis à esquerda e de expressões à direita precisa ser a mesma, sob pena de um erro como
em
a,b,c=1,2,3,4
ValueError: too many values to unpack (expected 3)
Swap de variáveis
Em programação muitas vezes é necessário inverter o conteúdo de 2 variáveis. Em situação normal, isso exige o uso de
uma variável auxiliar como em
>>> aux=a
>>> a=b
>>> b=aux
Python possui um mecanismo simples para realizar a troca sem usar variáveis adicionais. O mesmo exemplo acima pode
ser feito assim
a,b=b,a
>>> *a,b=seq
>>> a
[10, 20, 30]
>>> b
40
Exclusão de variável
Embora não seja usual, o programador pode excluir as variáveis quando estas deixarem de ser úteis. Não é usual, pois ao
encerrar o Python automaticamente tudo o que foi usado é excluído e os recursos liberados. Mas, havendo necessidade o
programador pode excluir variáveis com o comando del. Veja-se
>>> a=5
>>> b=6
>>> del a,b
>>> a
NameError: name 'a' is not defined
5.2 Tipos
Graças a essa distinção vista acima, pode-se pontuar a respeito de uma característica importante das variáveis. Cada
variável terá um tipo que sinalizará como ela será manipulada depois de criada. Os principais tipos são: numérico inteiro,
numérico real, alfanumérico e lógica.
Ao contrário de outras linguagens (como o C, por exemplo), as variáveis em Python não têm um tipo explicitamente
declarado. É o seu valor que determina qual é o seu tipo. 1 Então,
A=10.3 A é uma variável do tipo real, que em Pythons é conhecida como float
B=5 A variável B é do tipo inteiro.
C=10.0 A variável C é tipo float
HAL='ivo viu a uva' A variável HAL contém a frase ivo viu a uva
GA=True GA é uma variável do tipo lógico que tem o valor de verdadeiro
J=False J é uma variável do tipo lógico e tem o valor Falso
1 Esta regra nem sempre é verdadeira, por exemplo, ao usar o pacote Numpy. Mas, por enquanto pode-se aceitá-la como verdadeira.
• Dentro do computador, a matemática inteira é dezena de vezes mais rápida que a matemática real. Então quando
aplicável, sempre vale a pena ser mais eficiente.
• Mas, principalmente, o conjunto dos inteiros tem uma característica que o real não tem: a enumerabilidade. Tal
característica é muito importante (por exemplo, na indexação) e ela exige que o tipo seja inteiro em certos momentos.
Feita esta distinção, os conteúdos que uma variável numérica pode ter são:
flutuante : os mesmos dígitos e sinal e além destes, o sinal de ponto decimal. Note que usa-se em Python o ponto
decimal e não a vírgula decimal, herança dos países de língua inglesa. Opcionalmente pode-se ter a letra E ou e
significando exponencial. E, se presente, indica o expoente de 10, que deve ser multiplicado pelo número antes do
E. O expoente também pode ter opcionalmente um sinal que pode + ou -. Exemplos:
Nenhuma dessas modificações causa algum tipo de erro ou de manifestação do Python. São ações normais e corriqueiras.
Em alguns momentos da programação, é necessário explicitamente modificar um tipo de variável. Esta necessidade
já vai aparecer (ao tratar o comando input, por exemplo), mas ela vai ser vista aqui do ponto de vista formal. Para
mudar o tipo de uma variável pode-se usar
Obviamente a transformação só vai acontecer se ela for possível. Não adianta, por exemplo, definir A='alfa' e pedir
int(A), já que ’alfa’ não pode ser transformada em um número inteiro. Mas, se B='123' deve-se notar que B é uma
variável string (por causa das aspas), mas ela pode ser transformada em inteira e neste caso, valerá 123, pois só é formada
por dígitos numéricos. Já a conversão em string é sempre possível, e sempre que for ordenada será realizada.
Para a representação de números inteiros o Python usa um sistema de precisão ilimitada, que permite usar muitos
(muitos !) dígitos, veja-se por exemplo o fatorial de 50 é
30414093201713378043612608166064768844377641568960512000000000000. O programador não precisa
fazer nada (ao contrário de outras linguagens mais antigas como C ou C++). O Python simplesmente lança mão de
quantas casas forem necessárias para a representação numérica inteira pedida.
Já na representação flutuante, podem surgir problemas derivados do fato de que o Python usa para representação
interna um formato binário limitado composto de abcissa e mantissa. Em outras palavras, um número flutuante usa uma
quantidade finita de bits para ser representado, o que faz com que haja perda de precisão nessa representação. Veja-se
um exemplo prático (uma sessão real de Python)
>>> a=0.1
>>> print("{:2.5f}".format(a))
0.10000
>>> print("{:2.30f}".format(a))
0.100000000000000005551115123126
5.2.2 Nomes
A regra para dar nomes em Python (regras essas que se aplicam à nomeação de variáveis) são simples:
• uma única palavra, ou seja não se admitem espaços em branco dentro dos nomes.
• pode-se usar o caracter sublinha (_) para separar palavras no nome
• o primeiro caractere deve ser uma letra
• depois do primeiro pode-se usar letras ou números
• Letras maiúsculas são diferentes das letras minúsculas (ou seja OBA é diferente de Oba que não é a mesma coisa
que oba).
O leitor não deve se preocupar muito com estas regras, substituindo-as por algum bom senso: os nomes devem ser
autodeclarativos (sobre para que serve a variável), com nomes nem muito grandes (provocam erros de digitação) nem
muito pequenos (para que serve mesmo a variável B ?). Uma regra muito usada por aí sugere usar várias palavras ou
abreviaturas no nome, separando umas das outras pelo uso de maiúsculas. Usando esta regra pode-se ter
Os detratores da regra acima dizem que não se deve misturar maiúsculas e minúsculas no nome, pois isto acaba sendo
uma fonte de erros de digitação. Estes dizem que as variáveis devem ser todas minúsculas ou todas maiúsculas.
Enfim, a sugestão aqui é que cada leitor deve definir a sua regra de formação de nomes e se ater a ela, sempre visando
a minimização dos erros de digitação.
A partir da versão 3, o Python pode aceitar caracteres acentuados na formação de nomes, pois aqui por padrão usa-se
o conjunto de caracteres Unicode, através do Unicode Transformate Format-8 (UTF-8). Mas, pensando francamente,
não parece ser uma boa idéia: se você definir uma variável de nome SAÍDA e depois chamá-la de SAIDA, para o
Python serão duas variáveis distintas, e portanto aqui está uma nascente fonte de problemas. Tente não usar caracteres
acentuados ao programar. Você não vai se arrepender. Conteúdos dentro de aspas (constantes) podem e devem usar
caracteres acentuados: vamos homenagear a Língua Portuguesa, e dentro das aspas não se corre nenhum perigo. Como
em ESTADO='Paraná'.
>>> 10/3
3.3333333333333335
>>> 10//3
3
>>> 10%3
1
>>> a = 5
>>> b = a+2
>>> b
7
Uma maneira mais elaborada de saída é com o comando print(). É muito rico, com múltiplas opções, mas vamos co-
meçar lentamente. Na sua versão mais simples, o print admite uma lista de variáveis e eventualmente constantes a serem
escritas na saída padrão quando o programa for executado. A saída padrão é um conceito importante em computação
pessoal: trata-se do dispositivo que o computador usará para todas as saídas, quando nada for afirmado sobre ONDE
fazer a saída. Em computação usa-se o conceito de default nestes casos. Então a saída default é conhecida como saída
padrão e quase sempre é o monitor de vídeo. Vejam-se alguns exemplos
print(a) Imprime o valor da variável a.
print("o valor de a: ",a) Agora antes do valor da variável a, imprime-se a mensagem entre aspas. Ajuda
a identificar as saídas
print("a: ",a,"b: ",b) Imprime a e b identificando cada uma delas
print("Desligue agora") Imprime apenas a mensagem
print("Resultado ",x+22) Imprime a mensagem e depois o resultado de x+22. Note que o valor de x
permanece inalterado
>>> a=5
>>> b=6
>>> print(a,b)
5 6
>>> print(a,b,sep="#")
5#6
>>> print(a,b,sep="oba")
5oba6
>>>
S = π × R2
def area():
a=float(input("Informe raio"))
s=3.1415 * a
print("a área é: ",s)
area()
Mais um exemplo
def enesprim(qual):
count=1
candidato=1
while count<qual:
candidato=candidato+2
if prim2(candidato):
count=count+1
return(candidato)
Neste exemplo primeiro define-se a função prim2 (bastante otimizada) que recebendo um valor qualquer informa se ele é
ou não é primo. Depois define-se a função enesprim que recebe um n[umero inteiro x e devolve o x-ésimo número primo.
Finalmente, o script pede um número qualquer em aa, e com ele calcula o aa-ésimo número primo, e o joga em bb. Depois
este número é impresso.
Comandos condicionais
Uma característica onipresente em linguagens de programação é a capacidade de executar ou não um conjunto de instru-
ções a depender de uma variável lógica. Dizendo de outra maneira, pode-se comandar uma condição qualquer e se ela for
verdadeira (que no Python é True) então um conjunto de instruções será executado. Se a condição for falsa (em Python
False), ou nada é executado, ou também pode ocorrer, um segundo conjunto alternativo de instruções é executado.
O comando condicional por excelência em Python é if e ele têm o seguinte formato
if condição:
comando_1
comando_2
...
comando_n
Para escrever o comando, deve-se substituir a palavra condição por alguma condição relacional ou lógica, que ao final
informe um valor True ou False. A regra é que os comandos 1, 2, ... só serão executados se a condição for True. Já
ao final do bloco, o comando n será executado sempre independentemente da condição. Quem determina se o comando
está ou não vinculado ao if é o espacejamento no início da linha, chamada em programação de indentação.
Em outras linguagens, usam-se caracteres delimitadores para os blocos de comando ({ e } em C, Java e C++; begin e
end em Pascal e Delphi), mas em Python consoante com a proposta de limpeza da linguagem, usam-se as margens para
determinar as condições.
Como tudo na vida isto tem vantagens e desvantagens. Começando pelas primeiras, o código fica limpo e legível.
Quem sempre exigia dos programadores que respeitassem as margens, agora ganha um aliado importante: se as margens
forem bagunçadas o programa não funcionará bem. Além disso economizam-se caracteres dispensáveis.
Já a desvantagem decorre principalmente da inabilidade de muitos ambientes para manusear este tipo de arquivo.
Muitos editores se arvoram em trocar um certo número de brancos por um ou mais caracteres de tabulação, e fazer isto
é receita quase certa para problemas de operação dos programas. Além disso, muitos gerenciadores de download deixam
de respeitar essas margens, fazendo com o que o recebedor de um programa fonte Python tenha sempre que revisar com
cuidado o resultado de descargas de código.
Veja alguns exemplos
a = 5
if a==6:
print('ufa')
print('agora')
Primeiro a recebe 5. Daí 5 é comparado para igual com 6. A resposta é False. Com isso, os comandos identados abaixo
não são executados (no caso print(’ufa’)). Finalmente é impresso ’agora’ já que esta impressão independe do resultado
da comparação.
Quem inicia um bloco indentado é a presença dos dois pontos : após a condição. Ele sinaliza ao editor em uso que a
seguir deve-se respeitar a nova margem. Quando o programador quiser encerrar o bloco (e por conseguinte, a condição)
ele terá que recuar manualmente o cursor até o início da linha.
Um segundo formato para o comando condicional, conhecido como condicional composta é aquele que apresenta uma
condição e dois caminhos: um para o True e outro para o resultado False. Agora a separação entre um e outro é sinalizado
pela palavra else que também deve ser seguida por dois pontos. Acompanhe no exemplo
a = 7
if a>3:
print('oba')
else:
print('ufa')
print('foi')
51
Acompanhe o raciocínio: Primeiro a é comparado com maior para 3. A resposta é True já que 7 > 3 e com isso a
impressão de ’oba’ é feita. Como o resultado foi True, salta-se o bloco referente ao else:. Encerra o comando a impressão
de ’foi’ que independe do resultado da comparação. Veja agora um trecho parecido
a = 2
if a>3:
print('oba')
else:
print('ufa')
print('foi')
Agora a comparação resulta False (já que 2 > 3 é falso) e com isso a impressão de ’oba’ é saltada e depois a impressão
de ’ufa’ acontece. Novamente ’foi’ é impresso independentemente da comparação inicial.
6.1 Exercício
Nos exercícios a seguir, você deve simular o interpretador Python e descobrir qual valor vai ser impresso ao final. Considere
todas as variáveis como sendo do tipo inteiro. Todos os códigos estão sintaticamente corretos. A sugestão ‚ que depois
de ter calculado o valor na ponta do lápis, você confira o resultado com um computador real.
Exercício 1
def AA():
A=4
B=5
C=8
D=6
F=6
G=6
if F!=2:
C=A+F
if (D>=9)or(C!=4):
F=D+B
C=C-C
else:
D=D-B
if (D==5)and(D<8):
D=D-B
else:
if F<2:
F=A+B
else:
F=C+D
A=G-G
B=A*C
A=C+D
print(G+A+B-D)
AA()
Exercício 2
def AA():
A=9
B=5
C=9
D=2
F=3
G=8
if B>5:
if (G>9)or(D<=5):
C=C+D
if D==6:
C=G-G
Exercício 3
def AA():
A=4
B=7
C=6
D=2
F=7
G=9
if C!=6:
G=D+B
if (not(G==4))and(not(B>5)):
if B!=6:
G=G-A
G=G-C
if (D!=6)or(not(A>4)):
B=G*B
if A<5:
A=C*C
else:
G=C*B
else:
if (C!=9)or(B<=8):
C=C*F
else:
A=B*F
G=B*B
C=B*C
print(G+F+B-A)
AA()
Exercício 4
def AA():
A=9
B=7
C=6
D=9
F=5
G=6
if A<6:
C=F*A
if (C<=7)and(A>6):
if D==9:
D=D+F
else:
Exercício 5
def AA():
A=9
B=7
C=6
D=3
F=4
G=7
if G>4:
if (B<=9)or(F<5):
if D!=4:
if (not(A<=5))or(A>4):
B=G+F
else:
G=B-F
G=A+B
else:
B=F-D
G=G*D
else:
C=A+B
F=G*C
else:
if G>2:
if (A>=5)or(C!=3):
if B<5:
G=F*B
else:
D=F*G
else:
F=A+A
F=C*C
A=G+D
print(D+F+G-A)
AA()
Exercício 6
Exercício 7
def AA():
A=4
B=7
C=7
D=9
F=2
G=5
if C>=5:
if (A<=3)and(G!=2):
F=A-G
if A<=9:
A=F*D
A=C-A
else:
B=D*G
if (D<5)or(A!=4):
B=B-G
if B>=5:
F=D+G
else:
if (A==4)or(G>=4):
D=C*B
else:
F=C*G
F=F*G
C=A+A
print(G+A+C-D)
AA()
Exercício 8
def AA():
A=4
B=5
Respostas
1. 2. 3. 4. 5. 6. 7. 8.
11 5 -5 165 360 12 -8 34
Repetições
As repetições são estruturas da linguagem que asseguram a execução repetida de trechos de comandos, até que uma
determinada condição for satisfeita. Note que este conceirto faz parte do noasso dia a dia.
Por exemplo, uma caixa dágua posta a encher o fará até que atinja a capacidade total. Um forno assando um bolo
deverá operar até que o bolo esteja assado, uma esteira carregadeira de um navio opera até que o depósito do navio esteja
cheio ou enquanto o silo abastacedor tiver conteúdo, parando na condição que primeiro for atingida, um pneu de carro
receberá ar comprimido até que uma certa pressão seja atingida e a água do café vai esquentar até ferver ou um pouco
antes.
O que não falta na nossa vida são operações repetitivas que ocorrem até que uma condição seja atendida, ou o que
praticamente é a mesma coisa, enquanto certa condição perdurar.
7.1 while
Os comandos básicos em Python são while que pode ser traduzido por enquanto. Seu formato é
while <condição>:
comando_1
comando_2
...
comando_i
comando_n
Quando ele for encontrado será assim interpretado: primeiro a condição associada ao while será avaliada. Se ela for falsa,
ocorre um desvio desprezando todo o bloco indentado abaixo. No exemplo acima, se a condição for falsa, o próximo
comando a ser executado é o comandon . Agora, se a condição é verdadeira, o bloco indentado é executado. Quando ele
acabar, há um retorno (daí a repetição) ao início do bloco e a reavliação da condição. Enquanto ela for verdadeira, o
bloco fica em loop.
Logo, aqui vale uma advertência: quando usar um while garanta que em algum momento do bloco, a condição seja
tornada falsa, sob pena do seu programa nunca mais sair daí.
Por exemplo, seja somar os 33 primeiros números ímpares:
i=1
q=0
p=1
while i<34:
q=q+p
p=p+2
i=i+1
print(q)
7.2 break
Um comando que permite modificar o funcionamento do while é o break. Normalmente ele é colocado dentro de uma
condição, embora isto não seja obrigatório. Quando break é interpretado ele faz com que o ciclo do while, na verdade
qualquer ciclo, seja interrompido, forçando uma saída do bloco indentado.
Exemplo, seja um programa para calcular o triplo de um número digitado. O programa deve operar até ser digitado
um número negativo, que significará fim de processamento.
57
a=1
while 1==1:
if a<0:
break
a=int(input("informe o valor "))
print(3*a)
print('adeus')
Note que como vai-se usar o break para a saída do laço, escreve-se uma condição que sempre é verdadeira (conhecida na
lógica como uma tautologia) , que neste caso é 1 == 1, que, por óbvio, é sempre verdadeira.
Eis um trecho da execução desse programa:
i=1
while i<=3:
j=10
while j<=30:
j=j+10
print (i,j)
i=i+1
print('acabou')
(1, 20)
(1, 30)
(1, 40)
(2, 20)
(2, 30)
(2, 40)
(3, 20)
(3, 30)
(3, 40)
acabou
7.3 Continue
Este comando também serve para interromper um ciclo de processamento, mas diferentemente de break que encerra
inapelavelmente o laço, este comando continue encerra o processamento d euma interação e avança para a próxima
interação. Acompanhe a diferença entre os dois comandos
i=3
while i<10:
print(i,' ')
if i%7==0:
break
i=i+1
print('acabou')
7.4 For
O For é o grande interador do Python. Ele é uma expansão do comando for do C++. Lá no C++ o for funciona como
se fosse uma simplificação do while, mas aqui ele é mais do que isso. A mudança se deve ao conceito de interador. Numa
rápida explicação um interador é uma generalização do conceito de índice. Ele é uma generalização já que o índexador
só se aplica a conjuntos homogêneos indexados (conhecidos como arrays) e o interador se aplica a qualquer coleção de
objetos Python. Pode ser um array, mas pode ser também registros em um arquivo, itens em um conjunto, etc etc.
Veja um exemplo radical disso
s="Curitiba - Paraná - Brasil"
qtd=0
for c in s:
if c=="a":
qtd=qtd+1
print("achei ",qtd," a")
Ao executar o código acima, ele vai responder achei 4 a". Note que são 4 letras ’a’, sendo que o ’a’ acentuado de
Paraná, não conta, já que é outro caracter.
7.5 Exercícios
Nos exercícios a seguir, você deve simular o interpretador Python e descobrir qual valor vai ser impresso ao final. Todos
os códigos estao sintaticamente corretos. A sugestão é que depois de ter calculado o valor na ponta do lápis, você confira
o resultado com um computador real.
Exemplos
Seja o programa
def AA():
A=5
B=5
C=3
if C>=18:
while B<=18:
C=C-3
B=B+4
else:
C=C+4
B=B+2
print(C+C+B)
AA()
def AA():
A=4
B=3
C=6
D=1
C=C+6+3
while C>6:
B=D+7
while A<=14:
D=B+4
A=A+2
D=B+19
C=C-1
print(C+B+B)
AA()
def AA():
A=7
B=3
C=5
D=6
A=A+5+3
while A>=4:
B=D-4
if A>=10:
while C<=13:
C=C+6
B=D+3
else:
D=D-13
if D>4:
B=B+5
else:
B=D-5
A=A-2
print(B+B)
AA()
Exercício 1
def AA():
A=7
B=6
C=7
while C<16:
A=B+5
B=A+5
C=C+2
print(A+B+C)
AA()
Exercício 2
def AA():
A=6
B=2
C=3
Exercício 3
def AA():
A=8
B=2
C=2
if B!=16:
while C<16:
B=B+8
C=C+2
else:
while C<13:
A=B+7
C=C+2
print(B+B+C)
AA()
Exercício 4
def AA():
A=2
B=1
C=8
D=6
A=A+8+1
while A>=5:
C=D-5
while B<=16:
C=D-1
B=B+6
C=D-16
A=A-1
print(B+C+B)
AA()
Exercício 5
def AA():
A=4
B=2
C=1
D=5
B=B+1+2
while B>4:
C=A+5
if A>=9:
while A<=12:
C=C+2
A=A+6
C=D-16
else:
C=C-9
B=B-4
Exercício 6
def AA():
A=3
B=7
C=8
D=1
A=A+8+7
while A>5:
B=B+3
if B>=6:
while D<=16:
D=D+5
B=C-7
else:
C=B+15
if D>5:
C=C+8
else:
B=C+10
A=A-2
print(B+C)
AA()
Exercício 7
def AA():
A=6
B=2
C=1
D=3
C=C+1+2
while C>=6:
A=C+3
if D>=9:
while D<14:
D=D+4
B=B-3
else:
A=A+12
if D<8:
B=B+6
else:
A=A+9
C=C-2
print(A+B)
AA()
Exercício 8
def AA():
A=5
B=7
C=8
D=4
D=D+8+7
while D>=3:
A=D+3
if B>5:
while B<=19:
Exercício 9
def AA():
A=8
B=2
C=7
D=5
D=D+7+2
while D>7:
A=B+1
while B<=12:
C=C-1
B=B+1
C=C+12
D=D-1
print(C+B+C)
AA()
Exercício 10
def AA():
A=1
B=2
C=6
if A<=15:
while B<15:
A=A-7
B=B+4
else:
while B<16:
A=C+1
B=B+2
print(A+A+B)
AA()
Respostas
1 124 39 132 28 1 119 8 -67 173 -36
Listas
Uma lista em Python é uma coleção de coisas. Em outras linguagens, essas coisas precisam ser de mesmo tipo, mas em
Python, não. Podem ser coisas bem heterogêneas.
Cria-se uma lista em python usando-se os delimitadores colchetes. Uma lista é criada assim:
>>> a=[]
Criou-se aqui uma lista de nome a, inicialmente vazia. Para incluir coisas na lista, usa-se o método append, veja como
>>> a=[]
>>> a.append(1)
>>> a
[1]
>>> a.append('oi')
>>> a
[1, 'oi']
Outro jeito de criar uma lista é usando a função list como em
>>> b=list(range(6))
>>> b
[0, 1, 2, 3, 4, 5]
Note que o primeiro elemento da lista pode ser acessado para leitura fazendo-se
>>> a[0]
1
E podem ser alterados, como em
>>> a[0]='bacana'
>>> a
['bacana', 'oi']
Veja mais alguns exemplos, e estude-os...
>>> a = ['spam', 'eggs', 100, 1234]
>>> a
['spam', 'eggs', 100, 1234]
Os índices para as listas começam em 0 e crescem para a direita quando de usam números inteiros positivos. A função
len(lista) devolve o tamanho da lista. Índices negativos vem da direita para a esquerda. lista[-1] devolve o
último elemento da lista, lista[-2] o penúltimo e assim por diante. Veja isso tudo:
>>> x=[10,20,30,'oi','viva',4.5,99]
>>> x
[10, 20, 30, 'oi', 'viva', 4.5, 99]
>>> x[0]
10
>>> x[1]
20
>>> len(x)
7
>>> x[-1]
99
>>> x[-2]
4.5
65
8.1 Fatiamento
É uma operação fundamental em Python, pode ser usada em listas, tuplas, strings... É muito usada em MatLab, mas
sinceramente eu não consigo dizer quem é o ovo e quem é a galinha, isto quem veio antes. Tanto faz. Uma fatia é uma
especificação envolvendo um ou dois “dois pontos” e ela extrai um pedaço de uma lista, tupla ou string. A especificação
é
[começo da fatia:final da fatia:incremento]
começo o começo da fatia é o índice do seu início, sempre relativo a zero. Se nada for escrito aqui o valor default é 0.
final o final da fatia é o próximo número ALÉM do final. Ou seja este número é compatível com o início da numeração
em zero. O valor default é o tamanho da lista ou len(lista).
incremento É um valor muitas vezes omitido (e neste caso o valor default é 1), mas quando presente ele indica quanto
somar ao valor atual para obter o próximo valor.
8.2 Mais
Este texto descreve alguns pontos já abordados, porém com mais detalhes, e adiciona outros pontos e foi retirado de
http://turing.com.br/pydoc/2.7/tutorial/datastructures.html
list.append(x)
list.extend(L)
Prolonga a lista, adicionando no fim todos os elementos da lista L passada como argumento; equivalente a a[len(a):] = L.
list.insert(i, x)
Insere um item em uma posição especificada. O primeiro argumento é o índice do elemento antes do qual será feita a
inserção, assim a.insert(0, x) insere no início da lista, e a.insert(len(a), x) equivale a a.append(x).
list.remove(x)
Remove o primeiro item encontrado na lista cujo valor é igual a x. Se não existir valor igual, uma exceção ValueError é
levantada.
list.pop([i])
Remove o item na posição dada e o devolve. Se nenhum índice for especificado, a.pop() remove e devolve o último item
na lista. (Os colchetes ao redor do i indicam que o parâmetro é opcional, não que você deva digitá-los daquela maneira.
Você verá essa notação com frequência na Referência da Biblioteca Python.)
list.index(x)
Devolve o índice do primeiro item cujo valor é igual a x, gerando ValueError se este valor não existe
list.count(x)
list.sort()
list.reverse()
Inverte a ordem dos elementos na lista in place (sem gerar uma nova lista).
Um exemplo que utiliza a maioria dos métodos::
(N.d.T. Note que os métodos que alteram a lista, inclusive sort e reverse, devolvem None para lembrar o programador de
que modificam a própria lista, e não criam uma nova. O único método que altera a lista e devolve um valor é o pop)
>>> combs = []
>>> for x in [1,2,3]:
... for y in [3,1,4]:
... if x != y:
... combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
Note como a ordem dos for e if é a mesma nos dois exemplos acima.
Se a expressão é uma tupla, ela deve ser inserida entre parênteses (ex., (x, y) no exemplo anterior).
>>> vec = [-4, -2, 0, 2, 4]
>>> # criar uma lista com os valores dobrados
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> # filtrar a lista para excluir números negativos
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> # aplicar uma função a todos os elementos
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
>>> # invocar um método em cada elemento
>>> frutas = [' banana', ' loganberry ', 'passion fruit ']
>>> [arma.strip() for arma in frutas]
['banana', 'loganberry', 'passion fruit']
>>> # criar uma lista de duplas, ou tuplas de 2, como (numero, quadrado)
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> # a tupla deve estar entre parênteses, do contrário ocorre um erro
>>> [x, x**2 for x in range(6)]
File "<stdin>", line 1
[x, x**2 for x in range(6)]
^
SyntaxError: invalid syntax
>>> # achatar uma lista usando uma listcomp com dois 'for'
>>> transposta = []
>>> for i in range(len(matriz[0])):
... # as próximas 3 linhas implementam a listcomp aninhada
... linha_transposta = []
... for linha in matriz:
... linha_transposta.append(linha[i])
... transposta.append(linha_transposta)
...
>>> transposta
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
Na prática, você deve dar preferência a funções embutidas em vez de expressões complexas. A função zip() resolve muito
bem este caso de uso:
del também pode ser usado para remover totalmente uma variável:
>>> del a
>>> a
Traceback (most recent call last):
...
NameError: name 'a' is not defined
Referenciar a variável a depois de sua remoção constitui erro (pelo menos até que seja feita uma nova atribuição para
ela). Encontraremos outros usos para o comando del mais tarde.
Como você pode ver no trecho acima, na saída do console as tuplas são sempre envolvidas por parênteses, assim tuplas
aninhadas podem ser lidas corretamente. Na criação, tuplas podem ser envolvidas ou não por parênteses, desde que o
contexto não exija os parênteses (como no caso da tupla dentro a uma expressão maior).
Tuplas podem ser usadas de diversas formas: pares ordenados (x, y), registros de funcionário extraídos uma base de
dados, etc. Tuplas, assim como strings, são imutáveis: não é possível atribuir valores a itens individuais de uma tupla
(você pode simular o mesmo efeito através de operações de fatiamento e concatenação; N.d.T. mas neste caso nunca estará
modificando tuplas, apenas criando novas). Também é possível criar tuplas contendo objetos mutáveis, como listas.
Um problema especial é a criação de tuplas contendo 0 ou 1 itens: a sintaxe usa certos truques para acomodar estes
casos. Tuplas vazias são construídas por uma par de parênteses vazios; uma tupla unitária é construída por um único
valor e uma vírgula entre parênteses (não basta colocar um único valor entre parênteses). Feio, mas funciona:
>>> vazia = ()
>>> upla = 'hello', # <-- note a vírgula no final
>>> len(vazia)
0
>>> len(upla)
1
>>> upla
('hello',)
O comando t = 12345, 54321, ’hello!’ é um exemplo de empacotamento de tupla (tuple packing): os valores 12345, 54321
e ’bom dia!’ são empacotados juntos em uma tupla. A operação inversa também é possível:
>>> x, y, z = t
Isto é chamado de desempacotamento de sequência (sequence unpacking), funciona para qualquer tipo de sequência do
lado direito. Para funcionar, é necessário que a lista de variáveis do lado esquerdo tenha o mesmo comprimento da
sequência à direita. Sendo assim, a atribuição múltipla é um caso de empacotamento de tupla e desempacotamento de
sequência:
N.d.T. A sintaxe de sets do Python 3.1 foi portada para o Python 2.7, tornando possível escrever 10, 20, 30 para definir
set([10, 20, 30]). O conjunto vazio tem que ser escrito como set() ou set([]), pois sempre representou um dicionário vazio,
como veremos a seguir. Também existe uma sintaxe para set comprehensions, que nos permite escrever x*10 for x in [1,
2, 3] para construir 10, 20, 30.
8.9 Dicionários
Outra estrutura de dados muito útil embutida em Python é o dicionário, cujo tipo é dict (ver Mapping Types — dict).
Dicionários são também chamados de “memória associativa” ou “vetor associativo” em outras linguagens. Diferente de
sequências que são indexadas por inteiros, dicionários são indexados por chaves (keys), que podem ser de qualquer tipo
imutável (como strings e inteiros). Tuplas também podem ser chaves se contiverem apenas strings, inteiros ou outras
tuplas. Se a tupla contiver, direta ou indiretamente, qualquer valor mutável, não poderá ser chave. Listas não podem
ser usadas como chaves porque podem ser modificadas in place pela atribuição em índices ou fatias, e por métodos como
append() e extend().
Um bom modelo mental é imaginar um dicionário como um conjunto não ordenado de pares chave-valor, onde as
chaves são únicas em uma dada instância do dicionário. Dicionários são delimitados por chaves: , e contém uma lista de
pares chave:valor separada por vírgulas. Dessa forma também será exibido o conteúdo de um dicionário no console do
Python. O dicionário vazio é .
As principais operações em um dicionário são armazenar e recuperar valores a partir de chaves. Também é possível
remover um par chave:valor com o comando del. Se você armazenar um valor utilizando uma chave já presente, o antigo
valor será substituído pelo novo. Se tentar recuperar um valor usando uma chave inexistente, será gerado um erro.
O método keys() do dicionário devolve a lista de todas as chaves presentes no dicionário, em ordem arbitrária (se
desejar ordená-las basta aplicar o a função sorted() à lista devolvida). Para verificar a existência de uma chave, use o
operador in.
A seguir, um exemplo de uso do dicionário:
>>> d={}
>>> d
{}
>>> d[123]='oba' #a chave 123 corresponde a 'oba'
>>> d
O construtor dict() produz dicionários diretamente a partir de uma lista de chaves-valores, armazenadas como duplas
(tuplas de 2 elementos). Quando os pares formam um padrão, uma list comprehensions pode especificar a lista de
chaves-valores de forma mais compacta.
>>>
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}
>>> dict([(x, x**2) for x in (2, 4, 6)]) # use uma list comprehension
{2: 4, 4: 16, 6: 36}
N.d.T. A partir do Python 2.7 também existem dict comprehensions (abrangências de dicionário). Com esta sintaxe o
último dict acima pode ser construído assim x: x**2 for x in (2, 4, 6).
Mais adiante no tutorial aprenderemos sobre expressões geradoras, que são ainda mais adequados para fornecer os
pares de chave-valor para o construtor dict().
Quando chaves são strings simples, é mais fácil especificar os pares usando argumentos nomeados no construtor:
N.d.T. Naturalmente, por limitações da sintaxe, essa sugestão só vale se as chaves forem strings ASCII, sem acentos,
conforme a regras para formação de identificadores do Python.
Quando conveniente, a chave e o valor correspondente podem ser obtidos simultaneamente com o método iteritems().
Ao percorrer uma sequência qualquer, o índice da posição atual e o valor correspondente podem ser obtidos simultanea-
mente usando a função enumerate():
.get()
Retorna o valor associado à chave no dicionário. Se a chave não existe retorna valor. Se valor não é usado o padrão
é None.
.keys()
Retorna uma lista com todas as chaves do dicionário.
# python 3:
lista = list(range(100))
Criando uma lista com list comprehensions:
>>> lista = [x*2 for x in range(100)]
Percorrendo uma lista com for in:
>>> for x in lista:
# faça algo com x
Percorrendo uma lista, obtendo os valores e seus índices:
>>> for indice, valor in enumerate(lista):
print "lista[%d] = %d" % (indice, valor)
Percorrendo um pedaço de uma lista usando slicing:
>>> for x in lista[40:60]:
# faça algo com x
Ou caso lista contivesse listas aninhadas e quiséssemos fazer com que estas também fossem completamente copiadas, e
não somente referenciadas, usaríamos a função deepcopy():
>>> random.choice(lista)
7744
Gerando uma lista com 10 números aleatórios, com valores entre 0 e 99:
Strings
Além de números, Python também pode manipular strings (sequências de caracteres), que podem ser expressas de diversas
formas. Elas podem ser delimitadas por aspas simples ou duplas:
O interpretador exibe o resultado de operações com strings da mesma forma como elas são digitadas na entrada: dentro
de aspas, e com aspas, caracteres acentuados e outros caracteres especiais representados por sequências de escape com
barras invertidas (como '\t', '\xc3\xa9' etc.), para mostrar o valor preciso. A string é delimitada entre aspas
simples, exceto quando ela contém uma aspa simples e nenhuma aspa dupla. O comando print produz uma saída mais
legível para tais strings com caracteres especiais.
Strings que contém mais de uma linha podem ser construídas de diversas maneiras. Linhas de continuação podem ser
usadas, com uma barra invertida colocada na última posição para indicar que a próxima linha física é a continuação de
uma linha lógica:
Strings podem ser indexadas; como em C, o primeiro caractere da string tem índice 0 (zero). Não existe um tipo
específico para caracteres; um caractere é simplesmente uma string de tamanho 1. Assim como na linguagem Icon,
substrings podem ser especificadas através da notação de slice (fatiamento ou intervalo): dois índices separados por dois
pontos.
>>> palavra[4]
'a'
>>> palavra[0:2]
'Aj'
>>> palavra[2:4]
'ud'
Índices de fatias têm defaults úteis; a omissão do primeiro índice equivale a zero, a omissão do segundo índice equivale
ao tamanho da string sendo fatiada.:
Diferentemente de C, strings em Python não podem ser alteradas. Tentar atribuir valor a uma posição (índice ou fatia)
dentro de uma string resulta em erro:
81
>>> palavra[0] = 'x'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> palavra[:1] = 'Splat'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
Entretanto, criar uma nova string combinando conteúdos é fácil e eficiente:
>>> 'x' + palavra[1:]
'xjudaZ'
>>> 'Splat' + palavra[5]
'SplatZ'
Eis uma invariante interessante das operações de fatiamento: s[:i] + s[i:] é igual a s.
Intervalos fora de limites são tratados “graciosamente” (N.d.T: o termo original “gracefully” indica robustez no
tratamento de erros): um índice maior que o comprimento é trocado pelo comprimento, um limite superior menor que o
limite inferior produz uma string vazia.
>>> palavra[1:100]
'judaZ'
>>> palavra[10:]
''
>>> palavra[2:1]
''
Índices podem ser números negativos, para iniciar a contagem pela direita. Por exemplo:
>>> palavra[-1] # O último caractere
'Z'
>>> palavra[-2] # O penúltimo caractere
'a'
>>> palavra[-2:] # Os dois últimos caracteres
'aZ'
>>> palavra[:-2] # Tudo menos os dois últimos caracteres
'Ajud'
Observe que -0 é o mesmo que 0, logo neste caso não se conta a partir da direita!
>>> palavra[-0]
'A'
Intervalos fora dos limites da string são truncados, mas não tente isso com índices simples (que não sejam fatias):
>>> palavra[-100:]
'AjudaZ'
>>> palavra[-100]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range
Uma maneira de lembrar como slices funcionam é pensar que os índices indicam posições entre caracteres, onde a borda
esquerda do primeiro caractere é 0. Assim, a borda direita do último caractere de uma string de comprimento n tem
índice n, por exemplo:
0 1 2 3 4 5 6
+---+---+---+---+---+---+
| A | j | u | d | a | z |
+---+---+---+---+---+---+
-6 -5 -4 -3 -2 -1
A primeira fileira de números indica a posição dos índices 0...6 na string; a segunda fileira indica a posição dos respectivos
índices negativos. Uma fatia de i a j consiste em todos os caracteres entre as bordas i e j, respectivamente.
Para índices positivos, o comprimento da fatia é a diferença entre os índices, se ambos estão dentro dos limites da
string. Por exemplo, comprimento de palavra[1:3] é 2.
A função built-in (embutida) len() devolve o comprimento de uma string:
.capitalize()
Transforma o primeiro caractere de uma string em maísculo. Ignora caracteres acentuados ou que não sejam letras.
>>> "curitiba".capitalize()
'Curitiba'
>>> "ágora".capitalize()
ágora
.center()
Centraliza a string usando espaços à esquerda e à direita, até atingir a largura.
>>> "paraná".center(20)
' paraná '
>>> "paraná".center(2)
'paraná'
.count()
Conta a quantidade de substrings dentro da string
>>> "abracadabra".count("ab")
2
>>> "abracadabra".count("a")
5
.find()
Retorna a primeira ocorrência do substring dentro da string. Caso nada seja encontrado, retorna -1.
>>> "abracadabra".count("ab")
2
>>> "abracadabra".count("a")
5
Avaliadores
São eles: .isalpha(), .isdecimal(), .isdigit(), .islower(),.isnumeric(), .isspace(), .istitle(),
.isupper(). Retornam True caso a string seja composta exclusivamente de alfanuméricos, decimais, dígitos, minús-
culos, numéricos, espaços, títulos (a primeira letra de cada palavra em maiúsculo) e maiúsculas. Todos ignoram as letras
acentuadas.
.join()
Concatena todos os elementos dentro de iterável usando a string especificada como concatenador. A string pode ser vazia.
Os elementos do iterável devem ser string.
>>> a=['agua', 'fogo', 'xabu']
>>> ''.join(a)
'aguafogoxabu'
>>> '\n'.join(a)
'agua\nfogo\nxabu'
>>> print('\n'.join(a))
agua
fogo
xabu
>>> "curitibaparanabrasil".partition('ra')
('curitibapa', 'ra', 'nabrasil')
>>> "curitibaparanabrasil".partition('z')
('curitibaparanabrasil', '', '')
.replace()
Substitui n ocorrências da substring antiga pela nova. Se n não é fornecido, ele substitui todas.
>>> "curitibaparanabrasil".replace("ra","agora")
'curitibapaagoranabagorasil'
>>> "curitibaparanabrasil".replace("ra","zz",1)
'curitibapazznabrasil'
.split()
Divide a string transformando-a em uma lista usando um separador n vezes. Se o separador não é informado ele usa um
espaço em branco.
>>> "curitibaparanabrasil".split('a')
['curitib', 'p', 'r', 'n', 'br', 'sil']
>>> "curitiba parana brasil".split()
['curitiba', 'parana', 'brasil']
Muitos outros
Aqui estão só alguns, talvez os mais úteis e/ou principais. Consulte a documentação da versão de Python que você está
usando. Estão todos lá.
Strings Unicode
Um novo tipo para armazenar textos foi introduzido: o tipo unicode. Ele pode ser usado para armazenar e manipular
dados no padrão Unicode (veja http://www.unicode.org/) e se integra bem aos objetos string pré-existentes, realizando
conversões automáticas quando necessário.
Unicode tem a vantagem de associar um único número ordinal a cada caractere, para todas as formas de escrita
usadas em textos modernos ou antigos. Anteriormente, havia somente 256 números ordinais possíveis para identificar
caracteres. Cada texto era tipicamente limitado a uma “code page” (uma tabela de códigos) que associava ordinais aos
caracteres. Isso levou a muita confusão especialmente no âmbito da internacionalização de software (comumente escrito
como i18n porque internationalization é ’i’ + 18 letras + ’n’). Unicode resolve esses problemas ao definir uma única
tabela de códigos para todos os conjuntos de caracteres.
Criar strings Unicode em Python é tão simples quanto criar strings normais:
O u antes das aspas indica a criação de uma string Unicode. Se você desejar incluir caracteres especiais na string, você
pode fazê-lo através da codificação Unicode-Escape de Python. O exemplo a seguir mostra como:
O código de escape \u0020 insere um caractere Unicode com valor ordinal 0x0020 (o espaço em branco) naquela posição.
Os outros caracteres são interpretados usando seus valores ordinais como valores ordinais em Unicode. Se você possui
strings literais na codificação padrão Latin-1 que é usada na maioria dos países ocidentais, achará conveniente que os 256
caracteres inferiores do Unicode coincidem com os 256 caracteres do Latin-1.
Além dessas codificações padrão, Python oferece todo um conjunto de maneiras de se criar strings Unicode a partir
de alguma codificação conhecida.
Funções
Podemos criar uma função que escreve a série de Fibonacci até um limite arbitrário:
A palavra reservada def inicia a definição de uma função. Ela deve ser seguida do nome da função e da lista de parâmetros
formais entre parênteses. Os comandos que formam o corpo da função começam na linha seguinte e devem ser indentados.
Opcionalmente, a primeira linha lógica do corpo da função pode ser uma string literal, cujo propósito é documentar
a função. Se presente, essa string chama-se docstring. (Há mais informação sobre docstrings na seção Strings de
documentação.) Existem ferramentas que utilizam docstrings para produzir automaticamente documentação online ou
para imprimir, ou ainda permitir que o usuário navegue interativamente pelo código. É uma boa prática incluir sempre
docstrings em suas funções, portanto, tente fazer disto um hábito.
A execução de uma função gera uma nova tabela de símbolos, usada para as variáveis locais da função. Mais
precisamente, toda atribuição a variável dentro da função armazena o valor na tabela de símbolos local. Referências a
variáveis são buscadas primeiramente na tabela local, então na tabela de símbolos global e finalmente na tabela de nomes
embutidos (built-in). Portanto, não se pode atribuir diretamente um valor a uma variável global dentro de uma função
(a menos que se utilize a declaração global antes), ainda que variáveis globais possam ser referenciadas livremente.
Os parâmetros reais (argumentos) de uma chamada de função são introduzidos na tabela de símbolos local da função
no momento da invocação, portanto, argumentos são passados por valor (onde o valor é sempre uma referência para
objeto, não o valor do objeto). [1] Quando uma função invoca outra, uma nova tabela de símbolos é criada para tal
chamada.
Uma definição de função introduz o nome da função na tabela de símbolos atual. O valor associado ao nome da função
tem um tipo que é reconhecido pelo interpretador como uma função definida pelo usuário. Esse valor pode ser atribuído
a outros nomes que também podem ser usados como funções. Esse mecanismo serve para renomear funções:
>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89
Conhecendo outras linguagens, você pode questionar que fib não é uma função, mas um procedimento, pois ela não
devolve um valor. Na verdade, mesmo funções que não usam o comando return devolvem um valor, ainda que pouco
interessante. Esse valor é chamado None (é um nome embutido). O interpretador interativo evita escrever None quando
ele é o único resultado de uma expressão. Mas se quiser vê-lo pode usar o comando print:
>>> fib(0)
>>> print fib(0)
None
É fácil escrever uma função que devolve uma lista de números série de Fibonacci, ao invés de exibi-los:
87
>>> def fib2(n): # devolve a série de Fibonacci até n
... """Devolve uma lista a com série de Fibonacci até n."""
... resultado = []
... a, b = 0, 1
... while a < n:
... resultado.append(a) # veja mais adiante
... a, b = b, a+b
... return resultado
...
>>> f100 = fib2(100) # executar
>>> f100 # exibir o resultado
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
Este exemplo também introduz o operador in, que verifica se uma sequência contém ou não um determinado valor.
Os valores default são avaliados no momento a definição da função, e no escopo em que a função foi definida, portanto:
i = 5
def f(arg=i):
print arg
i = 6
f()
irá exibir 5.
print f(1)
print f(2)
print f(3)
[1]
[1, 2]
[1, 2, 3]
Se você não quiser que o valor default seja compartilhado entre chamadas subsequentes, pode reescrever a função assim:
aceita um argumento obrigatório (voltage) e três argumentos opcionais (state, action, e type). Esta função pode ser
invocada de todas estas formas:
Em uma invocação, argumentos nomeados devem vir depois dos argumentos posicionais. Todos os argumentos nome-
ados passados devem casar com os parâmetros formais definidos pela função (ex. actor não é um argumento nomeado
válido para a função parrot), mas sua ordem é irrelevante. Isto também inclui argumentos obrigatórios (ex.: par-
rot(voltage=1000) funciona). Nenhum parâmetro pode receber mais de um valor. Eis um exemplo que não funciona
devido a esta restrição:
lambda a, b: a+b.
Construções lambda podem ser empregadas em qualquer lugar que exigiria uma função. Sintaticamente, estão restritas
a uma única expressão. Semanticamente, são apenas açúcar sintático para a definição de funções normais. Assim como
definições de funções aninhadas, construções lambda podem referenciar variáveis do escopo onde são definidas (N.d.T
isso significa que Python implementa closures, recurso encontrado em Lisp, JavaScript, Ruby etc.):
>>> def fazer_incrementador(n):
... return lambda x: x + n
...
>>> f = fazer_incrementador(42)
>>> f(0)
42
>>> f(1)
43
Objetos em Python
Historicamente o paradigma de objetos nasceu como uma das reações da comunidade de software ao problema cada vez
mais importante da complexidade crescente do software. É só você olhar para os lados (bancos, companhias aéreas,
governos, grandes corporações, hospitais, um carro moderno, etc etc) para ver que a humanidade literalmente lança seu
futuro nas mãos do software e seja o que Deus quiser.
A idéia do objeto é encapsular (esconder, impedir que alguém indeterminado faça alterações, coisas desse estilo) dados
e procedimentos de maneira a garantir a integridade de uns e de outros. Dito de outra maneira, o paradigma de objetos
interpõe um intermediário (o objeto) entre os ativos tecnológicos (dados e procedimentos) e seus usuários (programas e
programadores que os manipulam).
Isto é necessário já que é uma evidência empírica que boa parte dos bugs (erros) de programa derivam de efeitos
colaterais de manipulação inadvertida de áreas comuns de dados dentro dos programas. Sobretudo, se não são os maiores
erros em número, certamente são os mais difíceis de corrigir por (aparentemente) muito pouco terem a ver com as ações
que os causaram. Em outras palavras quando a relação causa ⇔ efeito de um erro é tênue ou escondida, sua correção
demora e custa muito mais.
A explicação parece complexa e o é. Razão pela qual – na minha opinião – a metodologia de objetos se aplica
maravilhosamente a sistemas grandes e/ou complexos, mas para aprender a programar, ou mesmo para aplicações simples
é um exagero seu uso. É como matar um mosquito usando uma bala de canhão.
Mas aqui, de novo, a superioridade de Python: ele pode ser aprendido e usado o tempo todo como uma linguagem
imperativa: como se viu este é o melhor jeito de aprender a programar. Quando (e se) lá na frente, você sentir falta das
qualidades inerentes ao paradigma orientado ao objeto, voilà, não é que Python é 100% orientado ao objeto?
Dito isto, um objeto em Python é uma entidade que tem dados e procedimentos associados, e devidamente encobertos
(encapsulados). Um objeto é definido em python pelo uso da cláusula class. Veja como:
class carro:
Note que a definição termina por : o que caracteriza que ela continua. A próxima coisa é definir um objeto python de
nome __init__. Veja
def __init__(self):
Este objeto é o construtor e ele é automaticamente chamado pelo python toda vez que um objeto é instanciado (definido
e usado pela primeira vez). A variável self é o objeto propriamente dito. Note que o construtor é uma função, pelo que
também termina por :.
Nesta função construtora definem-se os valores iniciais do objeto que passarão a fazer parte dele assim que o objeto
for criado (instanciado). Acompanhe no exemplo completo
class carro:
def __init__(self):
self.kilo = 0
self.marca = 'peugeot'
self.portas = 5
Aqui definiu-se um objeto carro e disse-se que a kilometragem do carro é 0, a marca é peugeot e a quantidade de portas
é 5.
Depois dessa definição, pode-se criar quantos objetos se quiserem, como em
carro1 = carro()
carro2 = carro()
carro2.portas = 3
Neste caso, há 2 carros: carro1 e carro2. Em particular, o carro2 tem um número diferente de portas, a saber, 3.
Acompanhe
93
print(carro1.portas)
print(carro2.portas)
O python responderá 5 para a primeira impressão e 3 para a segunda.
11.1.1 Herança
Em uma relação de herança, existem no mínimo 2 classes envolvidas: A mais genérica chamada superclasse ou classe
pai. A outra é a mais específica, chamada de subclasse, classe filha ou ainda derivada. É comum em uma classe derivada
sobrecarregar os métodos da classe pai.
Arquivos
A função open() devolve um objeto arquivo, e é frequentemente usada com dois argumentos: open(nome_do_arquivo,
modo).
O primeiro argumento é uma string contendo o nome do arquivo. O segundo argumento é outra string contendo alguns
caracteres que descrevem o modo como o arquivo será usado. O parâmetro mode pode ser ’r’ quando o arquivo será
apenas lido, ’w’ para escrever (se o arquivo já existir seu conteúdo prévio será apagado), e ’a’ para abrir o arquivo para
adição; qualquer escrita será adicionada ao final do arquivo. A opção ’r+’ abre o arquivo tanto para leitura como para
escrita. O parâmetro mode é opcional, em caso de omissão será assumido ’r’.
No Windows, ’b’ adicionado a string de modo indica que o arquivo será aberto em modo binário. Sendo assim,
existem os modos compostos : ‘rb’, ‘wb’, e ‘r+b’. O Windows faz distinção entre arquivos texto e binários: os caracteres
terminadores de linha em arquivos texto são alterados ao ler e escrever. Essa mudança automática é útil em arquivos
de texto ASCII, mas corrompe arquivos binários como .JPEG ou .EXE. Seja cuidadoso e use sempre o modo binário ao
manipular tais arquivos. No Unix, não faz diferença colocar um ’b’ no modo, então você pode usar isto sempre que quiser
lidar com arquivos binários de forma independente da plataforma.
N.d.T. Para ler arquivos de texto contendo acentuação e outros caracteres não-ASCII, a melhor prática desde o
Python 2.6 é usar a função io.open(), do módulo io, em vez da função embutida open(). O motivo é que io.open()
permite especificar a codificação logo ao abrir um arquivo em modo texto para leitura ou escrita. Desta forma, a leitura
do arquivo texto sempre devolverá objetos unicode, independente da codificação interna do arquivo no disco. E ao escrever
em um arquivo aberto via io.open(), basta enviar strings unicode, pois a conversão para o encoding do arquivo será feita
automaticamente. Note que ao usar io.open() sempre faz diferença especificar se o arquivo é binário ou texto, em todos
os sistemas operacionais: o modo texto é o default, mas se quiser ser explícito coloque a letra t no parâmetro mode (ex.
rt, wt etc.); use use a letra b (ex. rb, wb etc.) para especificar modo binário. Somente em modo texto os métodos de
gravação e leitura aceitam e devolvem strings unicode. Em modo binário, o método write aceita strings de bytes, e os
métodos de leitura devolvem strings de bytes também.
>>> f.read()
'Texto completo do arquivo.\n'
>>> f.read()
''
O método f.readline() lê uma única linha do arquivo; o caractere de quebra de linha ('\n') é mantido ao final da string,
só não ocorrendo na última linha do arquivo, se ela não termina com uma quebra de linha. Isso elimina a ambiguidade
do valor devolvido; se f.readline() devolver uma string vazia, então é certo que arquivo acabou. Linhas em branco são
representadas por um '\n' – uma string contendo apenas o terminador de linha.
>>> f.readline()
'Primeira linha do arquivo.\n'
97
>>> f.readline()
'Segunda linha do arquivo.\n'
>>> f.readline()
''
O método f.readlines() devolve uma lista contendo todas as linhas do arquivo. Se for fornecido o parâmetro opcional
sizehint, será lida a quantidade especificada de bytes e mais o suficiente para completar uma linha. Frequentemente, isso
é usado para ler arquivos muito grandes por linhas, sem ter que ler todo o arquivo para a memória de uma só vez. Apenas
linhas completas serão devolvidas.
>>> f.readlines()
['Primeira linha do arquivo.\n', 'Segunda linha do arquivo.\n']
Uma maneira alternativa de ler linhas do arquivo é iterar diretamente pelo objeto arquivo. É eficiente, rápido e resulta
em código mais simples:
Essa alternativa é mais simples, mas não oferece tanto controle. Como as duas maneiras gerenciam o buffer do arquivo
de modo diferente, elas não devem ser misturadas.
O método f.write(string) escreve o conteúdo da string de bytes para o arquivo, devolvendo None.
N.d.T. Neste exemplo, a quantidade de bytes que será escrita no arquivo vai depender do encoding usado no console
do Python. Por exemplo, no encoding UTF-8, a string acima tem 18 bytes, incluindo a quebra de linha, porque são
necessários dois bytes para representar o caractere ’é’. Mas no encoding CP1252 (comum em Windows no Brasil), a
mesma string tem 17 bytes. O método f.write apenas escreve bytes; o que eles representam você decide.
Ao escrever algo que não seja uma string de bytes, é necessário converter antes:
N.d.T. Em particular, se você abriu um arquivo f com a função embutida open(), e deseja escrever uma string Unicode
x usando f.write, deverá usar o método unicode.encode() explicitamente para converter x do tipo unicode para uma string
de bytes str, deste modo: f.write(x.encode(’utf-8’)). Por outro lado, se abriu um arquivo f2 com io.open(), pode usar
f2.write(x) diretamente, pois a conversão de x – de unicode para o encoding do arquivo – será feita automaticamente.
O método f.tell() devolve um inteiro long que indica a posição atual de leitura ou escrita no arquivo, medida em bytes
desde o início do arquivo. Para mudar a posição utilize f.seek(offset, de_onde). A nova posição é computada pela soma
do deslocamento offset a um ponto de referência especificado pelo argumento de_onde. Se o valor de de_onde é 0, a
referência é o início do arquivo, 1 refere-se à posição atual, e 2 refere-se ao fim do arquivo. Este argumento pode ser
omitido; o valor default é 0.
Quando acabar de utilizar o arquivo, invoque f.close() para fechá-lo e liberar recursos do sistema (buffers, descritores
de arquivo etc.). Qualquer tentativa de acesso ao arquivo depois dele ter sido fechado resultará em falha.
>>> f.close()
>>> f.read()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: I/O operation on closed file
(Existem outras variações desse processo, úteis quando se precisa aplicar sobre muitos objetos ou o destino da represen-
tação string não é um arquivo; consulte a documentação do módulo pickle na Referência da Biblioteca Python.)
O módulo pickle é a forma padrão da fazer objetos Python que possam ser compartilhados entre diferentes programas
Python, ou pelo mesmo programa em diferentes sessões de execução; o termo técnico para isso é objeto persistente.
Justamente porque o módulo pickle é amplamente utilizado, vários autores que escrevem extensões para Python tomam
o cuidado de garantir que novos tipos de dados, como matrizes numéricas, sejam compatíveis com esse processo.
Pacotes em Python
13.1 Conceito
13.2 Instalação
13.3 uma amostra
Uma pequena amostra dos mais de 100.000 pacotes existentes no ambiente Python
PACOTE FINALIDADE
TENSORFLOW Implementa redes neurais em python. Autoria: google
PYEASYGA Implementa algoritmos de algoritmos genéticos
DEAP Implementa algoritmos de computação evolutiva, incluindo GA
BOKEH Apresentação de dados: tabelas, desenhos e inúmeras formas de apresentação
de dados
MATPLOTLIB Apresentação de dados
PYGAME Toda a infraestrutura para escrever games em python
TKINTER Interface TK para escrever aplicativos gráficos em python
NUMPY Computação numérica em python
TURTLE Simulação da linguagem LOGO
RANDOM Todas as tratativas para manuseio de números aleatórios
ASTROPY manuseia arquivos digitais FITS
DJANGO Framework web
FLASK Framework web
HUG Framework web
KERAS Machine learning, mais fácil que o tensor flow
SCIKIT-LEARN Machine learning
THEANO Machine learning
OpenCV Visão computacional
ORANGE3 Framework para data mining
SCRAPY Um crawler (spider fuçadeira) em python
PYODBC ODBC em python (para acessar bancos de dados)
SPHINX Documentador em python (originalmente desenvolvido para documentar o
python, mas pode ser usado em outros ambientes)
REQUESTS Requisições HTTP
COLLECTIONS Mantém histórico de processamentos em contendores. Elabora diversos proces-
samentos auxiliares em listas.
HEAPQ recupera os n maiores ou menores em uma coleção usando um heap
RE Processamento extensivo de expressões regulares, por exemplo pesquisando e
substituindo strings.
UNICODEDATA Normalização e compatibilização de strings UTF-8, UTF-16, ASCII, Latin1,
entre muitos outros.
TEXTWRAP reformatar texto em diversas modalidades.
101
DECIMAL Implementa a general decimal arithmetic specification da IBM.
CMATH Aritmética e álgebra complexa.
RANDOM Funções para números aleatórios.
DATETIME conversões e aritmética envolvendo diferentes unidades de tempo.
ITERTOOLS ferramentas adicionais de iteração. Por exemplo, ele gera todas as combinações
ou permutações de um contendor.
GZIP e BZ2 Comprime e descomprime conteúdos usando GZIP ou BZ2.
FNMATCH processa nomes de arquivos e diretórios.
OS interfaceia com o sistema operacional.
PYSERIAL Manusear a interface serial do computador.
PICKLE Serializar objetos.
CSV Manusear arquivos tipo CSV.
JSON Manusear dados JSON.
XML Manusear objetos XML.
BASE64 Converter de e para Base64.
STRUCT Manusear objetos binários complexos, registros variáveis aninhados, etc.
PANDAS Análise de dados envolvendo estatísticas, séries temporais e técnicas relaciona-
das.
FUNCTOOLS Ferramentas adicionais para definição de funções. (como wrapper=encapsular
uma função qualquer com processamento adicional, por exemplo um timmer).
QUEUE manipulação de filas e listas.
WEAKREF Indireções com referências fracas (compatibilidade com gabrage collection).
AST Abstract Sintax Tree, ou criar AST a partir de código fonte Python, permitindo
análise e manipulação.
DIS disassembly de código python.
SYS Manipulação de PATHs entre outras coisas.
URLIB Serviços de web.
SOCKET Serviços de socket.
TIME Manipulação de tempo.
IPADDRESS manipulação de endereços IP.
CGI Interfaces baseada em REST.
XMLRPC Procedimentos remotos.
HMAC Handshake para autenticação.
SSL camadas SSL para segurança.
THREADING Manipulação de threadings.
CONFIGPARSER Manipulação de arquivos de configuração.
LOGGING Manipular funções de logging.
RESOURCE Impõe limites de memória ou de CPU a programas (unix).
WEBBROWSER Iniciar um browser web.
QRCODE Gerador e manipulador de QRCODES.
PYSIM Programação simbólica (à moda do Maple)
MATPLOTLIB Gráficos em python
Pacote: Numpy
>>> a
array([[1, 2, 3],
[3, 4, 5],
[6, 6, 7]])
ambos jeitos devolvem. A explicação para isto é que na criação, tanto faz fornecer uma lista ou uma tupla.
Para indexar
a[1][2] é igual a 5 OU a[1,2] que igualmente é 5
Criação de PA A função arange() cria uma PA, cujos termos são a=np.arange(vl_inicial, até_vl_final, incremento),
como em
a=np.arange(1,5,0.5)
>>> a
array([ 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])
>>> a
array([1, 2, 3, 4])
>>> a.shape
(4,)
103
Cópia de array Para criar um array como cópia de outro, fazer
s3 = s2.copy()
>>> a1
[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.]
>>> a1.resize([2,6])
>>> a1
[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. 8. 9. 10. 11.]]
>>> a=[1,2,3,4]
>>> b=[0.1, 0.7, 8, 9]
>>> a
[1, 2, 3, 4]
>>> b
[0.1, 0.7, 8, 9]
>>> a+b
[1, 2, 3, 4, 0.1, 0.7, 8, 9]
>>> a=np.array([1,2,3,4])
>>> b=np.array([0.1, 0.7, 8, 9])
>>> a+b
array([ 1.1, 2.7, 11. , 13. ])
>>> a
array([1, 2, 3, 4])
>>>
>>> a+3
array([4, 5, 6, 7])
>>> b*5
array([ 0.5, 3.5, 40. , 45. ])
>>> x = (1, 2, 0)
>>> y = (4, 5, 6)
>>> print np.cross(x, y)
[12 -6 -3] para resolver isto ache o
determinante da matriz
i j k
1 2 0
4 5 6, com resultados em i, j e k
2x + y = 19
x - 2y = 2
cuja solução é (x=8 and y=3):
>>> coeffs = np.array([[2,1], [1,-2]])
>>> coeffs
[[ 2 1]
[ 1 -2]]
>>> consts = np.array((19, 2))
>>> consts
[19 2]
>>> np.linalg.solve(coeffs, consts)
[ 8. 3.]
Transposta
Funções matemáticas abs, sign, sqrt, log, log10, exp, sin, cos, tan, arcsin, arccos, arctan, sinh, cosh, tanh, arcsinh,
arccosh, and arctanh.
floor, ceil, and rint give the lower, upper, or nearest (rounded) integer:
>>> dir()
>>> np.random.rand(3,2)
array([[ 0.14022471, 0.96360618], #random
[ 0.37601032, 0.25528411], #random
[ 0.49313049, 0.94909878]]) #random
Para mostrar
Distribuição binomial Cria simulações desta distribuição. Usa 2 parâmetros: n, que significa o número de tentativas
e p que vem a ser a probabilidade de sucesso da distribuição (0 ≤ p ≤ 1). A função retorna para cada simulação o número
de sucessos. Lembrando que a probabilidade é
( )
n
P (N ) = pN (1 − p)n−N
N
) Veja-se o exemplo:
>>> n=10
>>> p=0.5
>>> s=np.random.binomial(n,p,1000)
O exemplo acima faz 1000 simulações, cada uma jogando 10 moedas e informando a quantidade de caras em cada
simulação.
Ordenação
>>> a = np.array([[1,4],[3,1]])
>>> np.sort(a) # sort along the last axis
array([[1, 4],
[1, 3]])
>>> np.sort(a,axis=None) #sort flattened array
array([1, 1, 3, 4])
>>> np.sort(a,axis=0) # sort along first axis
array([[1, 1],
[3, 4]])
14.1 Varejão
14.1.1 Para gravar arquivo de números
def testagra(a):
f=open("f:/p/up2017/ofid/primos.lis","w")
f.write(str(a)[1:-1])
f.close()
Pacote: Sympy
O Symbolic Python é um pacote Python que implementa um sistema de computação simbólica (CAS=Computer Algebra
System) no ambiente Python. Para entender o que é um sistema deste tipo, acompanhe:
computação numérica sqrt(8) é igual a 2.8284271247461903
computação simbólica sqrt(8) é igual a 2*sqrt(2)
Sendo que aqui tem-se uma constatação: ir do numérico para o simbólico não é possível, mas ir do simbólico para o
numérico é fácil (neste caso basta fazer sqrt(8).evalf() cuja resposta será a mesma de cima – até porque é calculada
do mesmo jeito: 2.8284271247461903).
Fica evidente que a computação simbólica abrange a computação numérica mas é muito (muito !) mais do que ela.
As vantagens de usar o sympy versus o Maple (por exemplo) são pelo menos duas: sympy é de graça (Maple custa
1.000 dólares) e por ser em python admite que você use tudo o que já sabe de python e também permite usar os mais de
135.000 pacotes também de graça.
Instalação e uso O sympy precisa ser instalado. Na versão para windows, você deve localizar o diretório scripts e nele
fazer pip install sympy em um computador que tenha acesso à Internet. Se quiser usar winpython, nele o sympy
já está pré-instalado. Num ou noutro, precisa importar o pacote. Faça from sympy import * ou algum comando
equivalente.
symbols Como você está num ambiente 100% python, precisa dizer que algumas variáveis são simbólicas. Isto é feito
pelo método symbols como em
from sympy import symbols
>>> x,y = symbols('x y')
>>> expr = x+2*y
>>> expr
x + 2*y
>>> expr + 1
x + 2*y + 1
>>> expr - x
2*y
>>> x*expr
x*(x + 2*y)
>>> expand(x*expr)
x**2 + 2*x*y
>>> factor(x**2 + 2*x*y)
x*(x + 2*y)
O sympy pode fazer todo o tipo de computação simbólica, como simplificar, calcular derivadas, integrais e limites, resolver
equações, trabalhar com matrizes, e muito mais, tudo de maneira simbólica. Ele inclui módulos para plotagem, impressão,
geração de código, física, estatística, combinatória, teoria dos números, geometria, lógica, etc. Vejamos um exemplo para
calcular: a derivada de
sin(x) × ex
, ∫
((ex × sin(x) + ex × cos(x))dx
e também ∫ ∞
sin(x2 )dx
−∞
109
>>> from sympy import *
>>> x, t, z, nu = symbols('x t z nu')
>>> init_printing(use_unicode=True)
>>> diff(sin(x)*exp(x), x)
x x
e .sin(x) + e .cos(x)
>>> integrate(exp(x)*sin(x) + exp(x)*cos(x), x)
x
e .sin(x)
>>> integrate(sin(x**2), (x,-oo, oo))
Substituição
Sympify Não confundir com simplify. Transforma um string em uma expressão SymPy.
>>> ex = sqrt(8)
>>> ex.evalf(20) # 20=tamanho
2.8284271247461900976
>>> ex2 = cos(2*x)
>>> ex2.evalf(subs={x:2.4})
0.0874989834394464
>>> expand((x+1)**2)
2
x + 2.x + 1
>>> expand((x+2)*(x-3))
2
x . x - 6
Integrais o comando que integra é integrate. O comando Integral serve para representar a integral e pode ser
calculado depois com x.doit(). Atente que integrate é com minúscula e Integral é com maiúscula. Acompanhe
>>> x = Integral(log(x)**2,x)
>>> x
/
| 2
| log (x) dx
/
>>> x.doit()
2
x.log (x) - 2.x.log(x) + 2.x
>>>
sin(x)
Limites
>>> limit(sin(x)/x, x, 0)
1
Solve Em Sympy a igualdade em uma equação é dada por Eq como em x2 = 1 ⇒ Eq(x**2,1) e para resolver esta
equação escreve-se
>>> solveset(Eq(x**2,1), x)
{-1, 1}
Note que isto pode ser escrito como solveset(Eq(x**2-1,0), x) e neste caso pode ser também solveset(x**2-1, x)
(já que é igual a zero). Para resolver um sistema de equações o comando é linsolve, veja
>>>linsolve([x+y+z-1,x+y+2*z-3],(x,y,z))
{(-y-1, y, 2)}
>>>linsolve(([1,1,1,1],[1,1,2,3])),(x,y,z))
{(-y-1, y, 2)}
Para sistemas não lineares, o comando é nonlinsolve.
>>>nonlinsolve([x*y-1,x-2],x,y)
{(2, 1/2)}
Para equaçoes diferenciais, use dsolve.
Matrizes Para fazer matrizes em Sympy use o objeto Matrix, como em Matrix([[1, -1], [3, 4], [0, 2]]).
Matrizes não são imutáveis, podendo ser alteradas.
Para a matriz M, sua forma é M.shape. Para achar a inversa fazer M ∗ ∗ − 1. Para achar a transposta, faça M.T .
Para o determinante, use M.det.
>>> M=Matrix([[1,2,3],[10,20,51],[8,-1,9]])
>>> M
+1 2 3 +
| |
|10 20 51|
| |
+8 -1 9 +
>>> M**-1
Segue a documentação tratando de teoria dos números (basicamente as tratativas referentes a números primos, depois
criptografia, depois matemática concreta, depois geometria, depois integração, lógica, séries, ... a documentação do pacote
tem (em maio de 2018) 1.878 páginas.
15.0.1 Exercício
1. Resolva (usando solveset) a equação:
de maneira numérica, usando o comando Integral de SymPy nos intervalos dados e depois calcule o valor numérico
da integral usando o método as_sum com 50 intervalos e tomando como parâmetro o ponto médio de cada intervalo:
(Forneça a resposta com 3 casas decimais)
>>> init_printing(use_unicode=True)
>>> e = Integral(...funçao...,(x,a,b))
>>> e
>>> e.as_sum(50,'midpoint').evalf()
1 2
15.0.2 Resposta
-4 3.317
Pacote: Astropy
Não proprietário O formato FITS é mantido pela comunidade científica internacional, em particular a comunidade
de astrônomos e astrofísicos e como tal ele não é formato proprietário. Atualmente a especificação é mantida pelo
Grupo de Trabalho FITS da IAU, União Internacional de Astronomia.
Bem documentado O formato FITS está completamente documentado na Referência FITS, livremente disponível. A
versão 3 foi publicada no Astronomy and Astrophysics volume 524 de dezembro de 2010.
Largamente adotado O formato é comumente usado pelos astrônomos. Há muitas aplicações de software para criar e
ver os arquivos, além de permitir a importação e exportação em outros formatos também usuais.
Transparência Uma grande vantagem é a simplicidade do formato. Nada é comprimido (o que introduziria grande
risco em caso da corrupção de um único bit...) e os dados são guardados ora em ASCII puro, ora em formatos de
codificação padronizados.
Auto contido Todas as informações necessárias para representar corretamente a imagem (na tela ou na impressora)
estão incluídas dentro do arquivo. Links externos ou fontes de recursos externos não são permitidos.
Independência de dispositivo Não há nenhuma dependência a algum hardware ou software específicos em nenhum
ponto do arquivo. Esta característica é muito importante na compatibilidade para a frente, pois não temos idéia
do que vem por aí.
16.1.1 Formato
O arquivo é formado por conjuntos de header + dados, tantos quantos houver interesse. O primeiro conjunto é chamado
primário e é obrigatório. Quando só tem o primário o arquivo é conhecido como Arquivo FITS básico e quando tem uma
ou mais extensões seguindo o conjunto primário é chamado de Arquivo FITS multi-extensão. Cada conjunto (chamado
na documentação de FITS structure) é formado por um número inteiro de blocos FITS, cada um com 2880 bytes e escrito
em ASCII puro (2880 = 80 × 36). Todos estes blocos ficam juntos, antes dos dados. Por ASCII puro entende-se caracteres
de 32 até 126.
O bloco de header contém uma série de palavras chaves seguida de seu valor. Assim, cada header tem espaço para
36 palavras chave. O último bloco de header deve conter a palavra chave END que marca o fim lógico do header. O que
sobrar de espaço depois, deve ser prenchido com espaços.
O conjunto de dados que vem depois, (se presente) deve consistir de um arranjo (array) de dados de 1 a 999 dimensões
(isto é definido pela palavra chave NAXIS O array inteiro é representado por um stream contínuo de bits que começa no
primeiro bit do primeiro bloco de dados. Cada dado consiste de um número fixo de bits como determinado na palavra
113
chave BITPIX. O índice do eixo 1 é o que varia mais rapidamente, depois o do eixo 2, e assim por diante. O último eixo
(NAXIS) é o que varia mais lentamente. Não há espaço ou qualquer caractere especial entre o último valor em uma linha
ou plano e o primeiro valor da próxima linha ou plano. A contagem começa em 1. Veja na figura como é isso:
Se o bloco de dados não preenche o último bloco ele deve ser preenchido com bits zero.
O bloco de header é formado por registros de 80 caracteres (36 por bloco) e eles consistem de uma palavra chave, um
indicador de valor (se necessário), um valor opcional e um comentário opcional. As palavras podem aparecer em qualquer
ordem, com poucas exceções. A palavra chave deve ter até 8 posições, alinhada à esquerda e com brancos à direita,
sempre em letras maiúsculas. As posições 9 e 10 podem ter ”=␣”. A seguir o valor da palavra chave e opcionalmente um
comentário. Entre o valor e o comentário deve-se escrever ”␣/␣”. Em todo este conteúdo (inclusive comentários) deve-se
usar apenas os caracteres ASCII de 32 até 126 – hexadecimal 20 até 7E. Variáveis de valor lógico devem ser representadas
por T ou F.
Eis as principais palavras chave:
SIMPLE Deve conter um valor verdade (T) se este arquivo obedece ao padrão FITS.
BITPIX Contém um inteiro e indica o número de bits que representa cada valor no array de dados. Os valores possíveis
são: 8, 16, 32, 64 – para inteiros – e -32 ou -64 para ponto flutuante.
NAXIS Inteiro não negativo não maior que 999 indicando quantos eixos tem o array de dados.
NAXISn Esta palavra deve estar presente para todos os valores de n de 1 até NAXIS. Indica o tamanho da dimensão do
array de dados.
END Indica final do cabeçalho. Esta palavra chave não tem valor associado
O número total de bits do array de dados primário, sem contar o preenchimento eventualmente necessário para completar
o bloco de 2880 caracteres, é Nbits = |BIT P IX| × (N AXIS1 × N AXIS2 × ... × N AXISm)
background_image_filename = 'c:\python\pedrofepo.jpg'
mouse_image_filename = 'c:\python\selo_coxa.jpg'
import pygame
from pygame.locals import *
from sys import exit
pygame.init()
screen = pygame.display.set_mode((1200, 800),0,32)
pygame.display.set_caption("hello")
background = pygame.image.load(background_image_filename).convert()
mouse_cursor = pygame.image.load(mouse_image_filename).convert_alpha()
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
exit()
screen.blit(background, (0,0))
x, y = pygame.mouse.get_pos()
x-= mouse_cursor.get_width() /2
y-= mouse_cursor.get_height() /2
screen.blit(mouse_cursor, (x,y))
pygame.display.update()
Este programa carrega duas imagens (a segunda com transparência), cria um ciclo eterno e nele deixa passar todos os
eventos (é o que faz event in pygame.event.get():) Se o evento for QUIT, isto significa que o usuário teclou no
’X’ que fecha a janela e portanto o programa deve ser encerrado. Senão, o programa desenha a tela principal começando
em 0,0 (que é o canto esquerdo superior). Daí, ele pega a posição do cursor nas variáveis x,y (de uma vez só, olha aí o
modernismo de python). Calcula um novo x,y (não entendi o porque do -, mas enfim), e desenha o cursor nessa nova
posição. Finalmente, o conjunto todo é atualizado através do comando pygame.display.update().
tratando eventos
O programa a seguir lista os eventos à medida em que eles ocorrem
import pygame
from pygame.locals import *
from sys import exit
pygame.init()
SCREEN_SIZE = (800, 600)
screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
exit()
print(event)
pygame.display.update()
117
Veja-se a seguir um programa de manuseio de listas (similar ao da pág 118-119 de [Men10].
V=[1,4,5,6,77,"aa",8,45,46,28,33,34,39]
P=[]
I=[]
for e in V:
x=str(e)
print(x)
print(x.isnumeric())
if x.isnumeric():
if e%2 == 0:
P.append(e)
else:
I.append(e)
else:
print("deu xabu")
print("Pares",P)
print("Impares",I)
Criando um dicionário:
def criahash():
import random
x = range(100)
som = 0
di = {}
for i in x:
aa = random.randint(1,1000)
print("%d - %d\n"%(i+1,aa))
som = som + aa
di[aa]=i+1
som= som / 100
print("media final = %8.2f" % som)
print(di)
def fibona(n):
# supoe um difibo = {0:1, 1:1}
if n in difibo:
return difibo[n]
else:
novo = fibona(n-1) + fibona(n-2)
difibo[n] = novo
return novo
import turtle,random
# x=10
# y=0
t=turtle.Pen()
turtle.bgcolor('black')
cor=['red','blue','green','yellow','pink','aquamarine','tomato','ivory','magenta']
for x in range(10,400,5):
t.width(random.randint(1,3))
t.forward(x)
# t.circle(x)
t.left(90)
# x=x+random.randint(1,5)
# x=x+5
import sys
Daí peça para ver se deu certo, pedindo para ver a variável sys.path. Ele deve responder com a lista de diretórios de
path. Emita o comando
sys.path.append('f:\\p\\n\\024')
Se você pedir para olhar a variável acima, verá que o novo diretório foi incluído sem problemas. Agora, emita o comando
from cpf import cpf
E agora pode usar a função cpf definida dentro daquele módulo fazendo
aa=cpf([1,1,1,2,2,2,3,3,3])
aa
Para criar uma lista com n zeros, fazer
lis = [0] * 33 # cria uma lista com 33 zeros
Pacote: Matplotlib
Este é um dos pacotes disponíveis no mundo Python para elaborar melhor as saídas na forma gráfica. Existem outros,
vale a pena uma pesquisa no PyPi (Python Package Index) .
Pacote maneiro para fazer desenhos e manipulações de imagens em Python. O pacote a ser instalado é o matplotlib
(pip install matplotlib) e ele exige um monte de dependências (o python, numpy, além de inúmeras outras).
Há 2 modos de uso do pacote: usar a interface procedural pyplot ou usar a API nativa da matplotlib, esta mais orientada
a objetos. A primeira é constituída por métodos (como xlabel, legend, etc) e elas podem ser usadas de duas maneiras: se
chamadas sem argumentos, devolvem o valor atual do parâmetro e se se chamadas com parâmetros elas atualizam este
valor. Veja a seguir uma chamada usando este método:
# caogato
import matplotlib.pyplot as plt
import numpy as np
def caogato():
ca=[23,34,24,28,67,54,76,99,23,26,66,55]
ga=[11,28,26,39,56,77,81,89,56,66,45,69]
plt.plot(ca,'r-',label='cães')
plt.plot(ga,'g-',label='gatos')
plt.legend()
plt.title('Cães e gatos em Curitiba')
plt.xlabel('ao longo dos meses')
plt.ylabel('milhares de animais')
plt.axis([0,11,0,120])
plt.xticks(np.arange(12),('jan','fev','mar',
'abr','mai','jun','jul','ago','set','out',
'nov','dez'),rotation=30)
plt.text(5,100,'mês de\n cachorro louco')
plt.grid()
plt.savefig('c:/p/python/caogato.png')
plt.show()
caogato()
121
18.3 O mesmo gráfico, via API
#caogato2
import matplotlib.pyplot as plt
import numpy as np
def caogato2():
ca=[23,34,24,28,67,54,76,99,23,26,66,55]
ga=[11,28,26,39,56,77,81,89,56,66,45,69]
fig,axe=plt.subplots()
axe.plot(ca,'r-',label='cães')
axe.plot(ga,'g-',label='gatos')
axe.legend()
axe.set_title('Cães e gatos em Curitiba')
axe.set_xlabel('ao longo dos meses')
axe.set_ylabel('milhares de animais')
axe.axis([0,11,0,120])
axe.set_xticks(range(12))
axe.set_xticklabels(['jan','fev','mar',
'abr','mai','jun','jul','ago','set','out',
'nov','dez'])
axe.grid()
axe.text(5,100,'mes de \ncachorro louco',rotation=45)
plt.savefig('c:/p/python/caogato2.png')
plt.show()
caogato2()
As cores são: ’b’=blue, ’g’=green, ’r’=red, ’c’=ciano, ’m’=magenta, ’y’=yellow, ’k’=black e ’w’=white. Os marcadores
são ’.’=ponto, ’o’=bola, ’v’=triângulo, ”̂=triângulo, ’<’=triângulo, ’>’=triângulo, ’s’=quadrado, ’p’=pentágono, ’*’=es-
trela, ’+’=mais, ’x’=vezes, ’D’=diamante, ’d’=diamante estreito, ’|’=linha vertical, ’_’=linha horizontal, ’-’=linha sólida,
’–’=linha picotada, ’-.’=linha ponto, ’:’=linha pontilhada (tem mais...)
ro significa ’red circles’. b- seria risco azul. r-- é red dashes, bs é blue squares e g^ é green triangles.
startangle
18.8 Histogramas
Desenha um histograma. Seu formato
x pode ser um array ou uma sequencia de arrays, que não precisam ter o mesmo comprimento.
Nota ∗ ∗ kwargs é aqui (como em todo o matplotlib) uma lista adicional (e opcional) de palavras chave e argumentos
que podem controlar mais aspectos do que está sendo pedido. Veja a documentação, a respeito.
Veja um exemplo bem bobo:
import numpy as np
import matplotlib.pyplot as plt
year, age_m, age_f = np.loadtxt
('c:/p/python/casamentos.txt',
unpack=True,skiprows=3)
fig = plt.figure()
ax = fig.add_subplot(111)
# Plot ages with male or female symbols as markers
ax.plot(year, age_m, marker='$\u2642$',
markersize=14, c='blue', lw=2,
mfc='blue', mec='blue')
ax.plot(year, age_f, marker='$\u2640$',
markersize=14, c='magenta', lw=2,
mfc='magenta', mec='magenta')
ax.grid()
ax.set_xlabel('Ano')
ax.set_ylabel('Idade')
ax.set_title('Idade média do primeiro
18.10 Exemplo
fig = plt.figure()
ax = fig.add_subplot(111)
cities = ['Boston', 'Houston',
'Detroit', 'San Jose', 'Phoenix']
linestyles = [{'ls': '-'}, {'ls': '--'},
{'ls': ':'}, {'ls': '-.'},
{'dashes': [2, 4, 2, 4, 8, 4]}]
for i, city in enumerate(cities):
filename = '{}.tsv'.format(city.
lower()).replace(' ', '_')
yr, pop = np.loadtxt(filename,
unpack=True)
line, = ax.plot(yr, pop/1.e6,
label=city, color='k', **linestyles[i])
ax.legend(loc='upper left')
ax.set_xlim(1800, 2020)
ax.set_xlabel('Year')
ax.set_ylabel('Population (millions)')
plt.show()
import numpy as np
import matplotlib.pyplot as plt
text_file = 'c:/p/python/mobydick.txt'
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
lcount = dict([(l, 0) for l in letters])
for l in open(text_file).read():
try:
lcount[l.upper()] += 1
except KeyError:
pass
norm = sum(lcount.values())
fig = plt.figure()
ax = fig.add_subplot(111)
x = range(26)
ax.bar(x, [lcount[l]/norm * 100 for l in letters], width=0.8,
color='g', alpha=0.5, align='center')
ax.set_xticks(x)
ax.set_xticklabels(letters)
ax.tick_params(axis='x', direction='out')
ax.set_xlim(-0.5, 25.5)
ax.yaxis.grid(True)
ax.set_ylabel('Letter frequency, %')
plt.show()
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.cm as cm
L, n = 2, 400
x = np.linspace(-L, L, n)
y = x.copy()
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X**2 + Y**2))
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
n = 1000
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
fig, ax = plt.subplots()
ax.imshow(julia, interpolation='nearest', cmap=cm.hot)
# Set the tick labels to the coordinates of z0 in the complex plane
xtick_labels = np.linspace(xmin, xmax, xwidth / 0.5)
ax.set_xticks([(x-xmin) / xwidth * im_width for x in xtick_labels])
ax.set_xticklabels(['{:.1f}'.format(xtick) for xtick in xtick_labels])
ytick_labels = np.linspace(ymin, ymax, yheight / 0.5)
ax.set_yticks([(y-ymin) / yheight * im_height for y in ytick_labels])
ax.set_yticklabels(['{:.1f}'.format(ytick) for ytick in ytick_labels])
plt.show()
18.20 mais
import matplotlib.transforms as transforms
import matplotlib.patches as patches
fig = plt.figure()
ax = fig.add_subplot(111)
x = np.random.randn(1000)
ax.hist(x, 30)
ax.set_title(r'$\sigma=1 \/ \dots \/ \sigma=2$',
fontsize=16)
trans = transforms.blended_transform_factory(
ax.transData, ax.transAxes)
rect = patches.Rectangle((1, 0), width=1, height=1,
transform=trans, color='yellow',
alpha=0.5)
ax.add_patch(rect)
plt.show()
18.24 Lemniscata
Em coordenadas cartesianas:
(x2 + y 2 )2 = 2a2 (x2 − y 2 )
Em coordenadas polares:
18.25 trifóide
#trifoide
import matplotlib.pyplot as plt
import numpy as np
fi=np.linspace(0.0, 6.5, 120)
x=np.zeros((120))
18.26 cardióide
Representação paramétrica:
x(φ) = 2a(1 − cosφ).cosφ
y(φ) = 2a(1 − cosφ).sinφ 0 ≤ φ < 2π
Em coordenadas polares:
r(φ) = 2a(1 − cosφ)
Em coordenadas cartesianas:
(x2 + y 2 )2 + 4ax(x2 + y 2 ) − 4a2 y 2 = 0
#cardioide
import matplotlib.pyplot as plt
import numpy as np
teta=np.linspace(0.0, 6.5, 120)
x=np.zeros((120))
Pacote: OpenCV
Definição
O pacote OCV (Open Source Computer Vision) agrega funções para processamento e análise de imagens. O pacote foi
desenvolvido originalmente em C++ e rapidamente migrado para Python. Usa como pré-requisitos os seguintes pacotes
Não precisa se preocupar, se o instalador detectar que estes pacotes não estão presentes ele (o instalador) vai carregar e
instalar estes dois pacotes.
A instalação do openCV se dá pelo comando
cd\python\scripts
>>>import cv2
Se o python responder >>> sem nenhuma outra mensagem, é porque a instalação deu certo.
Algumas funções
A seguir uma lista de algumas funções do pacote
Função o que faz forma de chamar
Ler uma imagem carrega para dentro do programa uma ou im=cv2.imread('arquivo.jpg',dica)
mais matrizes (vide canal)
dica é opcional e indica como a leitura deve ser feita. Seus valores:
143
def ima1():
import cv2
imagem=cv2.imread('jovem.jpg')
for i in range(0,imagem.shape[0],10):
for j in range(0,imagem.shape[1],10):
# (a,b,c)=imagem[i,j]
imagem[i:i+5,j:j+5]=(0,255,255)
cv2.imshow('olhe',imagem)
ima1()
import numpy as np
import cv2
im = cv2.imread('oba.jpg')
vermelho = (0,0,255)
verde=(0,255,0)
azul=(255,0,0)
cv2.line(im,(5,5),(30,60), verde)
cv2.rectangle(im,(20,30),(100,120),azul,-1)
(X, Y) = (im.shape[1]//2, im.shape[0]//2)
cv2.circle(im,(X,Y),30,azul)
import cv2
im=cv2.imread('oba.jpg')
recorte = im[100:200, 100:200]
cv2.imshow("Recorte",recorte)
cv2.imwrite("recorte.jpg",recorte)
cv2.INTER_CUBIC (slow)
import numpy as np
import cv2
im=cv2.imread('oba.jpg')
largura=im.shape[1]
altura=im.shape[0]
proporcao=float(altura/largura)
largura_nova=500
altura_nova=int(largura_nova*proporcao)
tamanho_novo=(largura_nova, altura_nova)
imredimens=cv2.resize(im,tamanho_novo,interpolation=cv2.INTER_AREA)
cv2.imshow('Resultado',imredimens)
cv2.waitKey(0)
Pacote: TKInter
Este pacote permite criar software Python com interface GUI (cara de aplicativo windows). Eis aqui uma aplicação
simples
#!/usr/bin/env python3
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.grid()
self.createWidgets()
def createWidgets(self):
self.quitButton = tk.Button(self, text='Tchal', command=self.quit)
self.quitButton.grid()
app = Application()
app.master.title('Aplicação simples')
app.mainloop()
E uma segunda
class Application(Frame):
def say_hi(self):
print("hi there, everyone!")
def createWidgets(self):
self.QUIT = Button(self)
self.QUIT["text"] = "QUIT"
self.QUIT["fg"] = "red"
self.QUIT["command"] = self.quit
self.QUIT.pack({"side": "left"})
self.hi_there = Button(self)
self.hi_there["text"] = "Hello",
self.hi_there["command"] = self.say_hi
self.hi_there.pack({"side": "left"})
root = Tk()
app = Application(master=root)
147
app.mainloop()
root.destroy()
Pacote: TensorFlow
É um produto freeware (licença Apache) desenvolvido pela Google para aprendizado de máquina. Substituiu seu an-
tecessor DistBelief que era proprietário. Além de ser um belo projeto de pesquisa ele é usado em produção em muitos
produtos google (tradução, classificação de fotos, busca, reconhecimento da fala humana, etc). Sua primeira versão foi
liberada em 9/11/15 e seu desenvolvimento começou em 2011.
Está em www.tensorflow.org. Embora tenha APIs para uso em C++, Java, Go seu uso mais completo e
documentado se dá em Python, já que a ferramenta está desenvolvida neste ambiente. Uma ótima oportunidade para
apreender e começar a usar esta linguagem.
Pode-se visualizar o vídeo em https://www.youtube.com/watch?v=oZikw5k_2FM. Se quiser, peça a tradução
simultânea para o português. Verá o TS em ação.
Eis aqui uma demonstração do vigor do Python neste ambiente. É uma das telas do TensorFlow, lá no site dele
(https://www.tensorflow.org/)
Vale lembrar a existência de um ambiente Python que pode ser executado avulso (a partir de um pendrive, por
exemplo), o que é ótimo quando você não tem os direitos de administrador na máquina que está usando. Trata-se
do chamado Python portátil e ele pode ser buscado em https://winpython.github.io/. Este sujeito já traz o
NUMPY instalado.
Tensor Flow
Este produto só roda em máquinas 64 bits (lembrem-se, ele não economiza recursos) e estando nesse ambiente, a instalação
é simples, basta fazer pip install tensorflow.
Depois de instalar, para verificar se deu tudo certo faça:
149
Deve aparecer a mensagem Oi, TensorFlow! indicando que a instalação foi bem sucedida.
Tensor
O ponto central em TF é o tensor. Trata-se de um array de valores primitivos configurados em uma matriz (Python). O
ranking de um tensor é o número de dimensões da matriz que o contém. Eis alguns exemplos:
Rede
Uma rede neural é uma série de operações TensorFlow dispostas em um grafo de nodos. Cada nodo tem zero ou mais
tensores de entrada e produz um tensor de saída.
Um exemplo completo está a seguir. Ele é um interpretador de dígitos escritos à mão, a partir dos dados do NIST.
É um conjunto de 70.000 imagens de dígitos manuscritos capturadas como imagens de 28 × 28 pixels (28 × 28 = 784)
associados a um vetor [0..9] que indica qual o número certo. Os dados estão divididos em 55.000 (treinamento) 10.000
(teste) e 5.000 validação. Lembre-se que quem aprova não pode ser o que treinou.
Veja um exemplo de um número 1
Se você rodar o programa abaixo terá uma acurácia de 92% aproximadamente. Melhorando os operadores da rede
neural chega-se facilmente a 97% e os melhores modelos chegam a 99.7 %.
Eis algumas imagens difíceis do conjunto
\verb+https://www.tensorflow.org/get_started/mnist/beginners+
O módulo abaixo é mnist_softmax.py...
import argparse
import sys
FLAGS = None
def main(_):
# Import data
mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)
# Create the model
x = tf.placeholder(tf.float32, [None, 784]) # dados de entrada
W = tf.Variable(tf.zeros([784, 10])) # a RN
b = tf.Variable(tf.zeros([10])) # os bias
y = tf.matmul(x, W) + b # o resultado da RN
# Define loss and optimizer
y_ = tf.placeholder(tf.float32, [None, 10])
# lugar onde vem a resposta certa
cross_entropy = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))
# quero minimizar a diferença entre y (calculado) e y_ (certo)
train_step =
tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
sess = tf.InteractiveSession() # cria a sessao
tf.global_variables_initializer().run()
# inicializa variáveis
# Train
for _ in range(1000):
# treinamento 1000 sessoes de 100 aleatorios
batch_xs, batch_ys = mnist.train.next_batch(100)
# coloca aqui os dados
sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
#roda a RN
# Test trained model
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
#y é igual a y_?
accuracy =
tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
#acurácia
print(sess.run(accuracy, feed_dict={x: mnist.test.images,
y_: mnist.test.labels}))
#imprime acurácia a partir das imagens de teste...
if __name__ == '__main__':
# descobre se isto está sendo chamado ou importado
parser = argparse.ArgumentParser()
parser.add_argument('--data_dir',
type=str, default='/tmp/tensorflow/mnist/input_data',
help='Directory for storing input data')
FLAGS, unparsed = parser.parse_known_args()
tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)
Se você rodar o programa acima terá uma rede neural funcional completa e obterá a acurácia de uma execução
(tipicamente 92%).
Um exercício
Sua tarefa aqui é razoavelmente simples:
4. Estude os tutoriais:
• Getting started
Pacote: Itertools
O módulo itertools implementa iteradores inspirado em APL, Haskell e SML. Cada um deles foi reconstruído para se
adaptar a Python eficiente.
geradores combinatórios:
153
Iterador Argumentos Resultados
product() p, q, … [repeat=1] cartesian product, equivalent to a nes-
ted for-loop
permutations() p[, r] r-length tuples, all possible orderings,
no repeated elements
combinations() p, r r-length tuples, in sorted order, no re-
peated elements
combinations_with_replacement() p, r r-length tuples, in sorted order, with re-
peated elements
product(’ABCD’, repeat=2) AA AB AC AD BA BB BC BD CA CB
CC CD DA DB DC DD
permutations(’ABCD’, 2) AB AC AD BA BC BD CA CB CD DA
DB DC
combinations(’ABCD’, 2) AB AC AD BC BD CD
combinations_with_replacement(’ABCD’, AA AB AC AD BB BC BD CC CD DD
2)
import itertools as it
def exe1():
for a in it.chain('ABCDEF'):
print(a)
exe1()
import itertools as it
def exe1():
for a in list('ABCDEF'):
print(a)
exe1()
dá como resposta A, B, C, D, E e F
import itertools as it
def exe1():
for a in it.combinations('ABCDEF',3):
print(a)
exe1()
Dá como respostas
('A', 'B', 'C')
('A', 'B', 'D')
('A', 'B', 'E')
('A', 'B', 'F')
('A', 'C', 'D')
('A', 'C', 'E')
('A', 'C', 'F')
('A', 'D', 'E')
Ou
it.combinations(range(5),3)
dará (0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 3),
(0, 2, 4), (0, 3, 4), (1, 2, 3), (1, 2, 4),
(1, 3, 4) e (2, 3, 4)
it.combinations_with_replacement('ABC',2)
dá
('A', 'A'), ('A', 'B'), ('A', 'C'),
('B', 'B'), ('B', 'C') e ('C', 'C')
itertools.compress(data, selectors) Retorna apenas os iteradores que são selecionados como True. Veja:
it.compress('ABCDE',[1,0,1,0,1]):
Retorna A, C e E
itertools.cycle(iterable) Retorna os itens da entrada de maneira cíclica ao infinito. Precisa ser interrompido.
itertools.dropwhile(predicate, iterable) Enquanto o predicado for falso, ele não devolve. Após o primeiro Verda-
deiro, volta tudo.
it.dropwhile(lambda x: x.isupper(),'AcBgChDE'):
é cBgChDE
import itertools as it
data='aaaaaaabbbbbbbbcccccccde'
groups = []
uniquekeys = []
for k, g in it.groupby(data):
groups.append(list(g)) # Armazena como uma lista
uniquekeys.append(k)
print(groups)
print(uniquekeys)
Retorna
print(k)
[['a', 'a', 'a', 'a', 'a', 'a', 'a'], ['b', 'b', 'b', 'b', 'b', 'b', 'b', 'b'], ['c', 'c', 'c'
print(g)
['a', 'b', 'c', 'd', 'e']
import itertools
def is_lt_100(x):
return x < 100
a = [1,2,3,4,1000,66,1201]
b = itertools.filterfalse(is_lt_100, a)
for a in map(pow,(2,3,5),(10,11,12)):
print(a)
deu como respostas 1024, 177147 e 244140625
import itertools as it
for a in it.starmap(pow,[(2,10),(3,11),(5,12)]):
print(a)
itertools.permutations(iterable, r=None)
\begin{verbatim}
import itertools as it
for a in it.permutations('ABC',2):
print(a)
deu
('A', 'B'), ('A', 'C'), ('B', 'A'),
('B', 'C'), ('C', 'A') e ('C', 'B')
itertools.product(iterables, repeat=1) Realiza o produto cartesiano. O product(A,B) faz o mesmo que ((x,y) for
x in A for y in B).
Para comutar o produto de um iterável com ele mesmo use a palavra repeat. Assim, product(A,repeat=4) faz o
mesmo que product(A,A,A,A).
import itertools as it
for a in it.product('ABC','123'):
print(a)
deu
('A', '1'), ('A', '2'), ('A', '3'),
('B', '1'), ('B', '2'), ('B', '3'),
('C', '1'), ('C', '2') e ('C', '3')
UTF-8
A informática convive – desde seu início – com uma dificuldade e tanto: como padronizar a utilização de códigos binários.
O objetivo é nobre: permitir a troca de objetos binários e a sua correta interpretação por parte de todos os parceiros
em uma comunicação qualquer. A necessidade é nova, a informática só apareceu na face da terra na década de 50 do
século passado. No início, cada fabricante usava seus códigos. A IBM, por exemplo, construiu toda a sua família de
equipamentos usando o código EBCDIC. Isto evoluiu para o código ASCII (início de 1960, comite ANSI-X3.2) que
acabou sendo adotado como padrão. Ele privilegiou o idioma inglês, e padronizou seus caracteres nas primeiras 128
posições do código ASCII. Aos demais idiomas do planeta ficou disponível a segunda parte do código ASCII (mais 128
posições). É aqui que o código BRASCII (NBR-9614:1986 e NBR-9611:1991 da ABNT) colocou os caracteres acentuados
do português. Assim como o Brasil, muitos outros países fizeram o mesmo. Isto apresentou pelo menos 2 problemas:
• Um arquivo composto no Brasil, quando impresso numa impressora fabricada na França, aparecia como uma série
de caracteres malucos.
• Idiomas com muitos caracteres (katakana, hiragana, hangul, tagalog,...) simplesmente não tinham como ser repre-
sentados no código ASCII. Não havia espaço.
23.1 Unicode
Em meados da década de 80, a academia e a indústria começaram a discutir propostas de resolver os 2 problemas acima.
Diversos padrões foram sugeridos e eles começaram a ser usados, na base do “cada um por si”. Uma primeira proposta
sugeria usar 16 bits (2 bytes) o que permitiria 216 = 65536 caracteres. Parecia muito, mas vale citar Peter Norton, que
disse há mais de 30 anos: na informática, não importa quanto você tem. Não é o suficiente.
Em 1991, criou-se o Consórcio Unicode e em outubro de 1991 o primeiro volume do padrão foi publicado. Em
1996, introduziu-se um mecanismo de codificação e com ele, a barreira dos 2 bytes foi ultrapassada. Agora, o espaço
de endereçamento do Unicode ultrapassou o milhão de caracteres, o que permitiu incluir idiomas históricos (hieróglifos
egípcios) ou mesmo idiomas muito pouco usados (Linear B por exemplo), além de algumas brincadeiras como o idioma
Klingom. O padrão atual consagra 1.114.112 códigos de ponto (codepoints), correspondendo ao intervalo hexadecimal
de 00.00.00 a 10.FF.FF. Note que nem todo codepoint indica um caracter, já que alguns deles são reservados a outras
finalidades.
Há alguns codepoints privados, que não têm significação no Unicode. Eles ficam para uma negociação entre remetente
e destinatário e podem ser usados para qualquer coisa (são eles: área privada: U+E000..U+F8FF com 6,400 caracteres;
área suplementar A: U+F0000..U+FFFFD com 65,534 caracteres e área suplementar B: U+100000..U+10FFFD com
65,534 caracteres).
O Consórcio Unicode trabalha junto com a ISO (International Organization for Standardization) já que o padrão
ISO/IEC 10646 é o próprio código Unicode. Um conceito importante é o de script. Trata-se de um conjunto de letras,
sinais e regras de escrita que agregam partes do Unicode e que são usados em conjunto de writing systems. Na versão 7
do Unicode, são 123 os scripts, e há uma lista de candidatos a serem incluídos.
157
• Compatibilidade reversa, já que caracteres da primeira parte do ASCII não sofrem modificação (1o bit=0). Desta
maneira qualquer arquivo ASCII que não use a segunda parte já é um arquivo UTF-8.
• Clara distinção entre caracteres de byte único (1o bit=0) e caracteres multi-bytes. Estes contém um primeiro byte
heading e um ou mais bytes de continuação. O heading tem 2 ou mais bits 1 seguidos por um zero enquanto os
bytes de continuação sempre começam por 10.
• Auto-sincronização. Bytes únicos, header e continuação não compartilham valores, indicando que o início do
caracteres está a no máximo 3 bytes para trás.
• Indicação do comprimento: O número de uns na alta ordem do byte heading indica a quantidade de bytes do
caractere, sem ser necessário examinar os seus bytes.
Veja-se um resumo do exposto
bits in¡cio fim tamanho byte1 byte2 byte3 byte4
7 U+0000 U+007F 1 0xxxxxxx
11 U+0080 U+07FF 2 110xxxxx 10xxxxxx
16 U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
21 U+10000 U+1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
Veja-se agora alguns exemplos de caracteres unicode de 1, 2, 3 e 4 bytes
23.3 Exemplos
1. Seja o seguinte conjunto de 5 caracteres UNICODE codificados em UTF-8.
F2B1B88DF4BAA8A7E192A9EF92A5F4A584BF
Seus codepoints em hexadecimal
0B1E0D 13AA27 14A9 F4A5 12513F
E em decimal
728589 1288743 5289 62629 1200447
2. Seja o seguinte conjunto de 5 caracteres UNICODE codificados em UTF-8.
39F6B2B6A503E68FAFF59A84B1
Seus codepoints em hexadecimal
39 1B2DA5 03 63EF 15A131
E em decimal
57 1781157 3 25583 1417521
E89A8DC4A9F69C82A1F4ABBABBCA8F
23.4.1 Resposta
1 : 868D 0129 19C0A1 12BEBB 028F 34445 297 1687713 1228475 655
Um estudo de otimização
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
Pode-se ver que 28 é o primeiro número triangular que tem mais do que 5 divisores. Qual é o valor do primeiro número
triangular que tem mais do que 500 divisores ?
t=1
a=1
cnt=0
while cnt <= 500:
cnt=0
a=a+1
t=t+a
i=1
while i<=t:
if t%i == 0:
cnt=cnt+1
i=i+1
print(t)
161
24.1.2 Segunda estratégia
Uma melhora evidente é interromper a busca quando o divisor alcança a raiz quadrada do número triangular: Para cada
divisor abaixo da raiz quadrada existe um acima dela. O código fica:
t=1
a=1
cnt=0
while cnt <= 500:
cnt=0
a=a+1
t=t+a
i=1
ttx = sqrt(t)
while i<=ttx:
if t%i == 0:
cnt=cnt+2
if t=ttx*ttx:
cnt=cnt-1 # correção quadrado perfeito
print(t)
Ainda assim, esta segunda estratégia continua muito demorada.
onde pi é um número primo e an seu expoente. Por exemplo, 28 = 22 × 71 . Daqui, o número de divisores de N , D(N )
de qualquer inteiro pode ser computado como
onde os an são os expoentes dos fatores primos que compõe o número N . No exemplo, os divisores de 28 são D(28) =
(2 + 1) × (1 + 1) = 3 × 2 = 6. Uma tabela de primos é necessária para aplicar esta relação. Uma estratégia para criá-la
pode ser (até 65500):
def primo(n):
# devolve True se n primo e False se n composto
import math
if n==1:
return False
if n<4:
return True
if n%2==0:
return False
if n<9:
return True
if n%3==0:
return False
r=math.floor(math.sqrt(n))
f=5
while f<=r:
if n%f==0:
return False
if (n%(f+2))==0:
return False
f=f+6
return True
def criatabprimos():
pri=[2]
i=1
j=3
while j<65500:
if primo(j):
def leiapri():
f=open("f:/p/.../primos.lis","r")
a=f.read()
pri=list(map(int,a.split(", ")))
print("feito")
Agora, o processamento
t=1
a=1
cnt=0
pri # lista de primos (acima...)
while cnt <= 500:
cnt=1
a=a+1
t=t+a
tt=t
i=0
while i < len(pri):
if pri[i]*pri[i]>tt:
cnt=cnt*2
break
expoente = 1
while tt%pri[i]==0:
expoente=expoente+1
tt=tt//pri[i]
if expoente>1:
cnt=cnt*expoente
if tt==1:
break
i=i+1
print(t)
Quarta estratégia
Ainda se pode melhorar mais, sabendo que os números triangulares também podem ser obtidos de acordo com
n × (n + 1)
t=
2
onde os componentes n e n + 1 são necessariamente co-primos (isto é, não têm qualquer fator primo comum nem divisor
comum). Aqui, o número de divisores D(t) pode ser obtido
ou
D(t) = D(n) × D((n + 1)/2) se n + 1 par
Cada componente é muito menor do que o número triangular. A tabela de primos também é muito menor (contém
apenas primos menores do que 1000) Mais, o resultado do componente n + 1 pode ser reaproveitado como n no próximo
número triangular, sem ser necessário recalculá-lo. Fica:
n=3
Dn=2
cnt=0
f=open("f:/p/.../primos.lis","r")
a=f.read()
24.1.4 Exercício
O objetivo deste exercício é treinar a implementação de algoritmos em python e também meditar sobre como modificações
na implementação de um mesmo problema a partir de conhecimentos matemáticos (Santa Matemática !) podem reduzir
radicalmente os tempos de processamento.
Para ajudar nesta meditação, implemente a alternativa que quiser e informe qual o número inteiro triangular que tem
mais do que
168
divisores.
Resposta
1385280
Pacote: Django
É um framework para construir aplicações WEB. Foi criado originalmente como sistema para gerenciar um site jornalístico
na cidade de Lawrence, no Kansas. Virou depois um projeto de código aberto.
25.1.2 Path
Você precisa fazer o python acessível de qualquer lugar. Assim, sua variável path deve refletir este fato. Para isso:
1. Painel de controle
2. Aba system
4. Procure a variável PATH e acrescente a ela ;c:\python3 ou o nome onde o python tiver sido instalado
cd\
mkdir lixopro
cd lixopro
python c:\python3\scripts\django-admin.py startproject mysite
O resultado disso é a criação de um diretório abaixo de lixopro chamado mysite onde o django vai guardar coisas. Eis o
que foi criado
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
• O mysite externo é um container para o seu projeto. O nome dele não interessa.
• manage.py é um utilitário de linha de comando que permite a você interagir com o projeto django. Mais em
https://docs.djangoproject.com/en/2.0/ref/django-admin/
• o mysite interno é o diretório do projeto. Você usará este nome para importar coisas dentro dele (por exemplo
mysite.urls).
165
• mysite/__init__.py é um arquivo vazio que diz ao python que este diretório deve ser um pacote python.
• mysite/setting.py configuração para o projeto django.
• mysite/urls.py As declarações de url. É uma tabela de conteúdo.
• mysite/wsgi.py Um entry=point para web-servers compatíveis com WSGI.
25.1.4 Começando
Vá nesse diretório e execute
> python manage.py runserver
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'mypassword',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
Deve-se notar que cada entidade deve ser uma classe. Os tipos de campo, (entre outros) podem ser: AutoField, BinaryFi-
eld, BooleanField, CharField, DateField, DateTimeField, DecimalField, DurationField, EmailField, FileField, FloatField,
ImageField, IntegerField, URLField
Os relacionamentos são indicados usando ForeignKey, ManyToManuField, OneToOneField.
Depois de montar seu banco de dados, é necessário dizer ao Django que a aplicação (polls no caso) está instalada.
Então em
/pro/mysite/mysite/settings.py
INSTALLED_APPS = [
'polls.apps.PollsConfig',
...
]
Agora deve-se rodar uma execução de manage para informar ao Django que foram feitas modificações no banco de
dados e ele deve obedecê-las.
/pro/mysite
Se quiser ver o que este cara fez, execute python manage.py sqlmigrate polls 0001 Ele vai listar o que irá
fazer.
Para fazer a implementação real no banco:
/pro/mysite
25.5 Resumão
1. Baixar Python e Django. Anotar os diretórios onde estão. Criar um path que acesse o python.
2. Criar um diretório (md pro) entrar nele e executar python c:\python\scripts\django-admin startproject mys
Este cara vai criar uma árvore de diretórios.
3. Para pôr o servidor em ação, vá em cd/pro/mysite e execute python manage.py runserver. A saída é com
quit().
8. Se tudo funcionou, ao chamar o servidor (runserver), depois um browser com 127.0.0.1:8000/nome/ deverá
aparecer o alo mundo.
9. Para configurar o banco de dados, atualize mysite/settings.py. Se for usar SQLite, nada a fazer.
INSTALLED_APPS = [
'nome.apps.NomeConfig',
'django.contrib.admin',
...
]
def __str__(self):
return self.campo descritivo
Agora, reexecutando o passo anterior, você vai ser sua entidade no admin
19. Em /pro/mysite/nome/urls.py faça a modificação
{% load static %}
<link rel="stylesheet" type ="text/css" href="{% static 'nome/style.css' %}" />
{% if latest_question_list %}
<ul>
...
23. Se quiser criar imagens... Em /pro/mysite/nome/static/nome/images/ crie uma imagem chamada background.gif
E depois, no estilo acima, faça
li a {
color: green;
}
body {
background: white url("images/background.gif") no-repeat;
}
Bibliografia
26.1 Python
para saber mais sobre Python
BEA13 BEAZLEY, David e JONES, Brian K. Python Cookbook. São Paulo, Novatec, 2013. 713p.
RAM15 RAMALHO, Luciano. Python Fluente. São Paulo, Novatec, 2015. 797p.
MEN10 MENEZES, Nilo Ney Coutinho. Introdução à Programação com Python. São Paulo, Novatec, 2010.
327p.
MCK18 MCKINNEY, Wes. Python para Análise de Dados. São Paulo, Novatec, 2018. 615p.
MUE16 MUELLER, John Paul, Começando a programar em Python para leigos Rio de Janeiro, Alta Books,
2016. 379p.
KIN15 KINSLEY, Harrison e McGUGAN, Will. Introdução ao desenvolvimento de Jogos em Python com
PyGame. São Paulo, Novatec, 2015.
PYTxx Comunidade Python Mundial. Site https://www.python.org.
PYTxx Comunidade Python Brasil. Site https://python.org.br.
KAN18 KANTEK, Pedro Luis Garcia Navarro. Python. Curitiba, UFPR, 2018. Disponível em
www.pkantek.com.br/atividades.
DOW16 DOWNEY, Allen B. Pense em Python. São Paulo, Novatec, 2016.
173
KNU71 KNUTH, Donald E. The Art of Computer Programming. Volumes 1 e 2. Reading, Massachussets,
Addison Wesley Publishing Company, 1971, 624p.
WIR89 WIRTH, Niklaus. Algoritmos e estruturas de dados. Rio de Janeiro, Prentice-Hall do Brasil, 1989, 245p.
KAO08 KAO, Ming-Yang. (ed.) Encyclopedia of Algorithms. New York, Springer, 2008. 1200p.
BAR87 BARROSO, Leônidas Conceição et alli. Cálculo Numérico (com aplicações). São Paulo, Harbra, 1987.
RUG88 RUGIERO, Márcia e LOPES, Vera Lúcia. Cálculo Numérico - aspectos teóricos e computacionais. São
Paulo, Pearson, 1988.
PAC78 PACITTI, Tércio e ATKINSON, Cyril. Programação e Métodos Computacionais. vol 1 e 2. Rio de
Janeiro, LTC, 1979.
CAM14 CAMPOS Filho, Frederico Ferreira. Algoritmos Numéricos. Rio de Janeiro, LTC, 2014.
if, 51
C, 31
imc, 157
C++, 41, 149
in, 88
c++, 31
indentação, 51
cardióide, 140
input, 47
cas, 109
int, 44, 47
chave, 74
integral, 111
ciclo de vida, 14
integrate, 111
class, 93
interador, 153
clipper, 29
ipl, 26
cobol, 27
Ipython, 39
codepoint, 157
iso, 157
condicional, 51
iterator, 153
conjunto, 74
itertools, 153
continue, 58
J, 33
Darthmout College, 26 jacopini, 15
default, 88 java, 32, 41, 149
dicionário, 74
dict, 74 linsolve, 111
diff, 111 lisp, 26, 43
dijkstra, 15 list comprehension, 71
distbelief, 149 listcomp, 72
divisão inteira, 45 loop, 57
divisão real, 45 lua, 34
django, 165
dois pontos, 51 mainstream, 35
mais, 45
ebcdic, 157 maiúsculas, 45
else, 51 map(), 70
encapsulamento, 93 maple, 109
eniac, 11 matplotlib, 121
enigma, 11 McCarthy, 26
equação, 109 menos, 45
expressão aritmética, 45 Minsky, 26
minúsculas, 45
factor, 110 multiplataforma, 35
fatiamento, 73 multiplicação, 45
175
módulo, 45
natural, 30
neumann, 13
nomes, 45
nonlinsolve, 111
numpy, 43
objeto, 93
opencv, 143
painel de controle, 37
palavra reservada, 44
parênteses, 45
pascal, 30, 41
peopleware, 10
PHP, 33, 41
pie, 125
pilha, 69
pizza, 125
programador, 11
programação funcional, 70
prolog, 26, 43
pygames, 117
PyPi, 121
python2, 46
python3, 46
pythonanywhere, 39
self, 93
set, 74
software, 10
str, 44, 47
sublinha, 45
subplot, 133
subtração, 45
symbols, 109
sympy, 109
system, 37
tautologia, 58
tela azul da morte, 39
tensorflow, 149
tiobe, 35
tipo, 43
trifóide, 139
tupla, 73
turtle, 117
variável, 41
vezes, 45
w3c, 157
web, 39
while, 57
winpython, 39
ímpares, 57
yes next
while logical condition: ? Loop Control for var in sequence: …
no finish
statements block break immediate exit statements block
continue next iteration
s = 0 initializations before the loop ☝ else block for normal Go over sequence's values
i = 1 condition with a least one variable value (here i) loop exit. s = "Some text" initializations before the loop
Algo: cnt = 0