Tabela de hash do ditado
A estrutura eficiente de tabelas de hash de chave/valor do Python é chamada de "dicionário". O conteúdo de um dicionário pode ser escrito como uma série de pares de chave-valor entre colchetes { }, por exemplo, dict = {chave1:valor1, chave2:valor2, ... }. O "dicionário vazio" é apenas um par vazio de colchetes {}.
A pesquisa ou a definição de um valor em um dicionário usa colchetes, por exemplo, dict['foo'] pesquisa o valor sob a chave 'foo'. Strings, números e tuplas funcionam como chaves, e qualquer tipo pode ser um valor. Outros tipos podem ou não funcionar corretamente como chaves (strings e tuplas funcionam bem porque são imutáveis). Procurar um valor que não esteja no dict gera um KeyError. Use "in" para verificar se a chave está no dict ou use dict.get(key) que retorna o valor ou None, caso a chave não esteja presente (ou get(key, not-found) permite especificar qual valor retornar no caso não encontrado).
## Can build up a dict by starting with the empty dict {} ## and storing key/value pairs into the dict like this: ## dict[key] = value-for-that-key dict = {} dict['a'] = 'alpha' dict['g'] = 'gamma' dict['o'] = 'omega' print(dict) ## {'a': 'alpha', 'o': 'omega', 'g': 'gamma'} print(dict['a']) ## Simple lookup, returns 'alpha' dict['a'] = 6 ## Put new key/value into dict 'a' in dict ## True ## print(dict['z']) ## Throws KeyError if 'z' in dict: print(dict['z']) ## Avoid KeyError print(dict.get('z')) ## None (instead of KeyError)
Um laço for em um dicionário itera sobre as chaves por padrão. As chaves vão aparecer em uma ordem arbitrária. Os métodos dict.keys() e dict.values() retornam listas das chaves ou valores explicitamente. Há também um items() que retorna uma lista de tuplas (chave, valor), que é a maneira mais eficiente de examinar todos os dados de valor de chave no dicionário. Todas essas listas podem ser transmitidas para a função sorted().
## By default, iterating over a dict iterates over its keys. ## Note that the keys are in a random order. for key in dict: print(key) ## prints a g o ## Exactly the same as above for key in dict.keys(): print(key) ## Get the .keys() list: print(dict.keys()) ## dict_keys(['a', 'o', 'g']) ## Likewise, there's a .values() list of values print(dict.values()) ## dict_values(['alpha', 'omega', 'gamma']) ## Common case -- loop over the keys in sorted order, ## accessing each key/value for key in sorted(dict.keys()): print(key, dict[key]) ## .items() is the dict expressed as (key, value) tuples print(dict.items()) ## dict_items([('a', 'alpha'), ('o', 'omega'), ('g', 'gamma')]) ## This loop syntax accesses the whole dict by looping ## over the .items() tuple list, accessing one (key, value) ## pair on each iteration. for k, v in dict.items(): print(k, '>', v) ## a > alpha o > omega g > gamma
Observação de estratégia: do ponto de vista do desempenho, o dicionário é uma das melhores ferramentas, e você deve usá-lo como uma maneira fácil de organizar os dados. Por exemplo, é possível ler um arquivo de registro em que cada linha começa com um endereço IP e armazenar os dados em um dict usando o endereço IP como a chave e a lista de linhas em que aparece como o valor. Depois de ler o arquivo inteiro, você pode procurar qualquer endereço IP e conferir a lista de linhas dele instantaneamente. O dicionário recebe dados dispersos e os transforma em algo coerente.
Formatação de ditado
O operador % funciona convenientemente para substituir valores de um dicionário em uma string por nome:
h = {} h['word'] = 'garfield' h['count'] = 42 s = 'I want %(count)d copies of %(word)s' % h # %d for int, %s for string # 'I want 42 copies of garfield' # You can also use str.format(). s = 'I want {count:d} copies of {word}'.format(h)
Del
O operador "del" faz exclusões. No caso mais simples, ele pode remover a definição de uma variável, como se ela não tivesse sido definida. Del também pode ser usado em elementos de lista ou frações para excluir essa parte da lista e para excluir entradas de um dicionário.
var = 6 del var # var no more! list = ['a', 'b', 'c', 'd'] del list[0] ## Delete first element del list[-2:] ## Delete last two elements print(list) ## ['b'] dict = {'a':1, 'b':2, 'c':3} del dict['b'] ## Delete 'b' entry print(dict) ## {'a':1, 'c':3}
Arquivos
A função open() abre e retorna um identificador de arquivo que pode ser usado para ler ou gravar um arquivo da maneira habitual. O código f = open('name', 'r') abre o arquivo na variável f, pronto para operações de leitura, e usa f.close() quando terminar. Em vez de "r", use "w" para gravação e "a" para adição. O laço for padrão funciona para arquivos de texto, iterando pelas linhas do arquivo. Isso funciona apenas para arquivos de texto, não binários. A técnica de laço for é uma maneira simples e eficiente de analisar todas as linhas de um arquivo de texto:
# Echo the contents of a text file f = open('foo.txt', 'rt', encoding='utf-8') for line in f: ## iterates over the lines of the file print(line, end='') ## end='' so print does not add an end-of-line char ## since 'line' already includes the end-of-line. f.close()
A leitura de uma linha por vez tem a vantagem de que nem todo o arquivo precisa caber na memória de uma só vez, o que é útil se você quiser analisar cada linha em um arquivo de 10 gigabytes sem usar 10 gigabytes de memória. O método f.readlines() lê todo o arquivo na memória e retorna o conteúdo como uma lista das linhas. O método f.read() lê o arquivo inteiro em uma única string, o que pode ser uma maneira prática de lidar com o texto de uma só vez, como com as expressões regulares que vamos ver mais adiante.
Para gravação, o método f.write(string) é a maneira mais fácil de gravar dados em um arquivo de saída aberto. Ou você pode usar "print" com um arquivo aberto, como "print(string, file=f)".
Arquivos Unicode
Para ler e gravar arquivos codificados em Unicode, use o modo "t" e especifique explicitamente uma codificação:
with open('foo.txt', 'rt', encoding='utf-8') as f: for line in f: # here line is a *unicode* string with open('write_test', encoding='utf-8', mode='wt') as f: f.write('\u20ACunicode\u20AC\n') # €unicode€ # AKA print('\u20ACunicode\u20AC', file=f) ## which auto-adds end='\n'
Exercite o desenvolvimento incremental
Ao criar um programa Python, não escreva tudo em uma etapa. Em vez disso, identifique apenas um primeiro marco, por exemplo, "a primeira etapa é extrair a lista de palavras". Escreva o código para chegar a esse marco e apenas imprima suas estruturas de dados nesse ponto. Em seguida, faça um sys.exit(0) para que o programa não avance para as partes não concluídas. Quando o código do primeiro marco estiver funcionando, você poderá trabalhar no código do próximo. Conferir a impressão das variáveis em um estado pode ajudar você a pensar em como transformar essas variáveis para chegar ao próximo estado. O Python é muito rápido com esse padrão, o que permite fazer uma pequena alteração e executar o programa para ver como ele funciona. Aproveite esse retorno rápido para criar seu programa em pequenas etapas.
Exercício: wordcount.py
Combinando todo o material básico do Python (strings, listas, dicionários, tuplas, arquivos), tente o exercício de resumo wordcount.py nos Exercícios básicos.