import pylab
def temp_max_min(f_ent):
"""
Lê temperaturas mensais de várias cidades, calcula valores máximos e mínimos.
Mostra o resultado num gráfico.
"""
# lê dados
f_in = open(f_ent)
dados = []
cidade = f_in.readline()
while cidade != '':
dados.append([float(valor) for valor in cidade[:-1].split()])
cidade = f_in.readline()
# calcula máximo e mínimo
lista_valores_mes = zip(*dados)
maximos = [max(mes) for mes in lista_valores_mes]
minimos = [min(mes) for mes in lista_valores_mes]
# mostra resultados
pylab.figure(1)
absissa = range(1,13)
pylab.xlabel('Meses')
pylab.ylabel('Temperaturas')
pylab.title(r'$\mathrm{M\acute aximo\,e\,M\acute inimo}$')
pylab.text(8,22,'Max')
pylab.text(8,18,'Min')
pylab.plot(absissa,maximos,'r-o',absissa, minimos,'b-^')
pylab.show()
Podemos visualizar o resultado.
A primeira fase está implementada entre as linhas 8 e 14. Os dados são lidos linha a linha (linhas 11 e 14). Cada linha vê os seus elementos separados e guardados numa lista, na forma de números em vírgula flutuante (linha 13). Essa lista é por sua vez guardada no contentor definido na linha 10. Na linha 13 usamos listas definidas por compreensão. O seu significado é semelhante ao dos conjuntos em matemática: A é o conjunto dos elementos x que satisfazem a condição y. O código pode ser substituído por outro mais normal.
# por compreenção
res = [float(valor) for valor in cidade[:-1].split()]
# equivalente "normal"
res = []
for valor in cidade[:-1].split():
res.append(float(valor))
As listas por compreensão podem ser mais complexas. Desde logo, podemos ter uma condição de filtragem.
# por compreenção
res = [float(valor) for valor in cidade[:-1].split() if float(valor) > 0 ]
# equivalente "normal"
res = []
for valor in cidade[:-1].split():
if float(valor) > 0:
res.append(float(valor))
Podemos ter também uma lista por compreensão dentro de outra. Uma vez habituados a elas saberemos apreciar a sua concisão e clareza.
Na segunda fase manipulamos a lista de listas (linhas 15 a 18). Aqui é crucial o uso da operação zip(*args). Dado um número variável de dados funciona como um fecho éclair: junta o que está na mesma posição. Quando, em vez de darmos os argumentos separados, os damos dentro de uma lista, temos que fazer um pouco mais de ginástica e separar esses elementos. Graças ao modo como o zip está definido basta usar a marca * antes do nome da lista.
>>> x = [1,2,3]
>>> y = ['a','b','c']
>>> zip(x,y)
[(1, 'a'), (2, 'b'), (3, 'c')]
>>> tudo = [x, y]
>>> tudo
[[1, 2, 3], ['a', 'b', 'c']]
>>> zip(tudo)
[([1, 2, 3],), (['a', 'b', 'c'],)]
>>> zip(*tudo)
[(1, 'a'), (2, 'b'), (3, 'c')]
>>>
Mas precisamos mesmo do zip? Não, mas a solução seria mais trabalhosa!
>
# com zip
lista_valores_mes = zip(*dados)
#sem zip
lista_valores_mes = []
for indice_mes in range(12):
mes = []
for indice_cidade in range(len(dados)):
mes.append(dados[indice_cidade][indice_mes])
lista_valores_mes.append(mes)
As listas por compreensão vêm de novo em nosso auxílio para nos facilitar a vida, relativamente à obtenção dos valores máximos e mínimos. O leitor pode gerar código alternativo, caso não se sinta confortável com o uso das listas por compreensão. Com o tempo e a prática o à vontade virá!
Na terceira fase mostramos os dados (linhas 19 a 28). Não há muito a dizer. O comando plot faz o trabalho por nós. As outras coisas são basicamente cosmética.
Sem comentários:
Enviar um comentário