Você está na página 1de 4

Roteiro: Mapas, Dicionrios e Tuplas

Roteiro 9: Tuplas e Dicionrios


Objetos imutveis
Podemos categorizar os objetos com que tratamos at o presente momento com base no conceito de mutabilidade. Um objeto mutvel se o(s) valor(es) que armazena podem ser modificados. Com base nessa definio, os objetos numricos de Python, bem como as strings, so objetos imutveis. Voc pode estar se questionando como isso pode ser verdade, j que voc pode ligar variveis a esses tipos e modificar seus valores. Por exemplo, podemos fazer: a = 10 a=a+1 ou ainda s = "labprog1" s = s.upper() Na verdade, em ambos casos o que est ocorrendo que h dois objetos envolvidos: o original e o segundo, que construdo como resultado da manipulao do primeiro com base em algum operador. Vamos ler atentamente o primeiro exemplo. O comando a = 10 uma atribuio. Do lado direito do igual h uma expresso que cria um objeto inteiro (o "10"). E o lado esquerdo determina uma varivel. O efeito da atribuio ligar a varivel "a" ao objeto "10". At este momento, observe, h apenas um objeto do interesse do nosso programa na memria. Vejamos agora o que faz o comando a=a+1 Trata-se de uma nova atribuio. Do lado direito h uma expresso feita com base na operao "+" e nos operandos "a" e "1" (sendo o primeiro uma varivel e o segundo um objeto). A avaliao da expresso faz com que "a" seja substitudo por "10" e as regras da adio para inteiros fazem com que um novo objeto seja criado: "11". Esse o resultado da avaliao da expresso do lado direito dessa atribuio. Finalmente, a ltima parte da instruo ser realizada, que a ligao da varivel indicada do lado esquerdo ao objeto resultante do lado direito. Assim, "a" fica ligada ao objeto "11". O mais importante aqui voc perceber que o objeto "10" original no foi alterado. Ele foi apenas "abandonado" porque "a" no mais se liga a ele. Objetos dos tipos numricos e strings de Python so imutveis por construo. Isto , eles foram projetados para que, uma vez criados, no possam mais sofrer alteraes. Essa deciso permite que os objetos sejam "compartilhados" por diferentes partes de um mesmo programa sem que uma interfira na outra. Mais adiante veremos como essa "interferncia" pode ocorrer.

Objetos Mutveis
Ao contrrio dos objetos vistos acima, objetos mutveis podem ter seu estado modificado. Dentre os objetos que j vimos neste laboratrio, pelo menos os do tipo lista e as "tartarugas" do turtle eram mutveis. Vejamos um exemplo de manipulao de um objeto mutvel. >>> lista = list("abcde") >>> lista ["a", "b", "c", "d", "e"] >>> lista[0] = "x" >>> lista ["x", "b", "c", "d", "e"] >>> Observe que a lista teve seu valor modificado. Mas ser que este fenmeno no igual ao que observamos com o "a = a + 1" acima? A resposta no. Neste caso, o que ocorreu que o prprio objeto original foi modificado. O mesmo objeto lista que continha os elementos 'a', 'b', 'c', 'd', 'e' foi efetivamente modificado e passou a conter os elementos 'x', 'b', 'c', 'd', 'e'.

Aliasing
Relembre que o fato de um tipo ser ou no imutvel depende exclusivamente do projetista do tipo. Por outro lado, perceba que essa deciso afeta diretamente o usurio do tipo. Imagine, por exemplo, o que pode ocorrer se duas variveis compartilham um nico objeto. Considere o seguinte trecho de cdigo. valores = [i**2 for i in range(10)] # ou qualquer outra lista de valores print zera_pares(valores) Qual o resultado esperado? Bom, bastante provvel que o programador deste trecho de cdigo, bem como um leitor dele, entenda que a funo "zera_pares" deve ler a lista passada como argumento e retornar outra contendo os mesmos valores da lista original, exceto pelos pares que devem ser trocados por 0. Nesse caso, tudo funcionar como esperado. Contudo, possvel que algum programador da funo a implemente da seguinte forma: def zera_pares(numeros): for i in range(len(numeros)): if numeros[i]%2 == 0: numeros[i] = 0 return numeros Esta implementao ainda funciona no programa acima, mas ela tem um efeito total diferente do primeiro caso. E o programador deve estar plenamente consciente desta diferena, porque ela pode ter efeitos importantes no resto do cdigo. Considere, por exemplo, a seguinte mudana no programa original acima. valores = [i**2 for i in range(10)] # ou qualquer outra lista de valores print zera_pares(valores) print [v for v in valores if v%2 == 0] O efeito desejado desse programa que a segunda linha imprima a lista com a mudana dos pares por zeros e que a terceira linha imprima apenas a lista dos pares que foram zerados na linha anterior. Contudo, o efeito final deste programa depende da implementao da funo zera_pares. Questo 1. Digite a sada deste programa se a funo zera_pares modificar a lista passada como argumento. Questo 2. Digite a sada do mesmo programa se a funo zera_pares no altera a lista passada como argumento.

Tuplas
Tuplas so tipos bastante semelhantes a listas. A principal diferena que so imutveis. A sintaxe para escrever literais de tuplas semelhante de listas. Contudo, ao invs de colchetes, usamos parnteses para tuplas. >>> x = (1,2,3) >>> x (1, 2, 3) Observe que voc no pode alterar o contedo de tuplas. Isso significa que nenhum dos mtodos de listas que permitem modificar seu contedo est disponvel para tuplas. >>> x = (1,2,3) >>> x >>> x[0] = 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment Contudo, diversos operadores permitem construir novas tuplas a partir de tuplas existentes. Por exemplo, podemos construir uma tupla com parte dos valores de uma tupla, usando slices: >>> t = tuple(range(10)) >>> t >>> t[3:7]

Mltiplas atribuies
A facilidade para fazermos mltiplas atribuies em Python simplesmente uma extenso da instruo de atribuio para lidar com o conceito de tuplas. Quando separamos a expresso do lado direito por vrgulas, Python entende que o que se quer uma tupla. Assim, podemos escrever: x, y = 10, 20

Dicionrios ou mapas
Um dicionrio (ou um mapa como chamarei mais freqentemente) um mapeamento entre elementos de dois tipos diferentes. A idia que o mapa seja uma forma bem primitiva de banco de dados em que podemos armazenar elementos, vinculando-os a uma chave de acesso. Vejamos um exemplo simples de uso para implementar uma agenda telefnica simples. fone = {} fone["ccc"] = "3310 1027" fone["dsc"] = "3310 1120" O primeiro comando acima uma atribuio que liga a varivel fone ao objeto do tipo mapa descrito por "{}". Neste caso, optamos por iniciar com um mapa vazio. As duas outras linhas apenas associam as strings dos telefones s chaves "ccc" e "dsc". Observe que a sintaxe envolvida bastante familiar sintaxe que voc conhece para listas e strings. A principal diferena, por ora, que o ndice usado uma "string" ao invs de ser um inteiro, como costumvamos fazer. Para acessar os valores, usamos a mesma sintaxe. Naturalmente, tentar acessar um valor associado a uma chave inexistente causar um erro. >>> print fone["dsc"] 3310 1120 >>> print fone["dee"] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'dee'

Inicializao de dicionrios
No exemplo anterior, optamos por inicializar o dicionrio vazio e inserir os elementos a ele um-a-um. H, contudo, uma sintaxe apropriada para inicializar um dicionrio com pares chave-valor prdefinidos. Neste caso, poderamos inicializar a agenda anterior desta forma. fone = {"ccc":"3310 1027", "dsc":"3310 1120"}

Mtodos de dicionrios
Tal como outros tipos, dicionrios suportam vrias operaes diferentes. Pesquise a documentao de Python sobre dicionrios e documente os seguintes mtodos, usando asserts como fizemos na aula anterior. keys() values() items() has_key() copy() clear() get()

Questo 3. Escreva asserts para documentar seu entendimento dos mtodos acima. Explore tantas possibilidades quanto puder.

Iterando sobre dicionrios


comum precisarmos iterar sobre os elementos de um dicionrios. As duas formas abaixo registram como podemos fazer isso: for chave in mapa.keys(): print chave, mapa[chave] ou for chave,valor in mapa.items(): print chave, valor Observe que em um mapa no h ordem nos elementos armazenados. Se voc quiser iterar sobre os elementos seguindo certa ordem, precisar fazer isso usando alguma externa de apoio. Uma forma muito usada iterar sobre a lista ordenada das chaves. for chave in sorted(mapa.keys()): print chave, mapa[chave] Observe que a funo "sorted" acima retorna uma verso ordenada da lista anterior, sem alterar a original. Nos exerccios abaixo explore os conceitos vistos neste roteiro da melhor forma possvel. Questo 4. Escreva uma funo que receba uma lista de valores numricos e que retorne o menor e o maior nmero da lista (no use as funes min e max). Questo 5. Escreva uma funo que receba uma string e retorne um dicionrio representando a contagem de caracteres contidos na string. O dicionrio resultante deve conter exclusivamente os caracteres presentes na string. assert conta_caracteres("ababaca") == {'a':4, 'b':2, 'c':1} assert conta_caracteres("outro") == {'o':2, 'r':1, 't':1, 'u':1} assert conta_caracteres("aaa bb") == {'a':3, 'b':2, ' ':1} Questo 6. Escreva uma funo que receba uma string contendo um texto e uma segunda string de caracteres. A funo deve retornar um dicionrio representando a contagem de caracteres contidos na string dos caracteres indicados na segunda string. assert conta_caracteres2("ababaca","ab") == {'a':4, 'b':2} assert conta_caracteres2("outro","ao") == {'a':0, 'o':2}

Você também pode gostar