Mais um ano que começa.
A finalidade deste blogue não se alterou: servir de apoio à cadeira de IPRP, da licenciatura em Engenharia Informática da Universidade de Coimbra.
quarta-feira, 16 de setembro de 2015
sexta-feira, 30 de janeiro de 2015
Exame Recurso - Pergunta 1b
As respostas dadas pela generalidade dos(as) alunos(as) denota uma incompreensão de aspectos básicos e fundamentais de Python. Em Python tudo são objectos, e os objectos têm atributos. O nome é um dos atributos, e é através do nome que chegamos a outro valor, o valor. Assim, temos por exemplo:
Mas também se fizermos:
>>> x = 5 >>> x 5 >>> a = ‘xpto’ >>> a xptoNeste exemplo, criámos objectos (5, ‘xpto’) e demos-lhes um nome (x, a).
Mas também se fizermos:
>>> def acme(n): … return 2*n … >>>Criamos também um objecto, agora do tipo função, e estamos a dar-lhe o nome acme. Se agora perguntarmos pelo valor do objecto de nome acme o que recebemos de volta é o descritor da função:
>>> acme <function acme at 0x102778488>Então, no caso da pergunta do exame, quando fazemos:
a = funcaoEstamos a dizer que a é um outro nome para o objecto de tipo função, funcao. Logo, ao fazermos:
>>> print(a)o que vai aparecer é a impressão do valor associado ao objecto de nome a, que é o mesmo do associado a funcao:
>>> def funcao():
… print('128')
…
>>> a = funcao
>>> a
<function funcao at 0x102778510>
Notar que pode agora usar o nome a em vez de funcao e obter o mesmo resultado:
>>> funcao() 128 >>> a() 128
Exame Recurso - Pergunta 1a
Nesta pergunta estavam envolvidos vários conceitos: alcance das variáveis (local, global), passagem de parâmetros (real, formal) e mutabilidade.
Na primeira situação, na chamada da função f1, a lista l (variável global, mutável) é usada como parâmetro real. Deste modo, no início da execução da função, l e lista são nomes de objectos que têm a mesma identidade. No entanto, na primeira instrução de f1 a atribuição lista = [1,2,3] faz com que os nomes ficam associados a objectos diferentes. Deste modo, todas as alterações a lista não afectam l, pelo que na linha 12 vai aparecer o valor (inalterado) de l = [1,2].
Na segunda situação, ao contrário da anterior, não é desfeita a ligação dos nomes l e lista ao mesmo objecto. Tratando-se de um objecto mutável, todas alterações feitas ao parâmetro formal serão reflectidas no parâmetro real, pelo que ao acrescentarmos 3 à lista usando o método append, essa alteração vai também afectar l. Logo, na linha 17, vai aparecer [1,2,3].
Na segunda situação, ao contrário da anterior, não é desfeita a ligação dos nomes l e lista ao mesmo objecto. Tratando-se de um objecto mutável, todas alterações feitas ao parâmetro formal serão reflectidas no parâmetro real, pelo que ao acrescentarmos 3 à lista usando o método append, essa alteração vai também afectar l. Logo, na linha 17, vai aparecer [1,2,3].
quinta-feira, 8 de janeiro de 2015
Teste Final - Pergunta 4
Esta pergunta envolvia manipular um ficheiro em que cada linha é formada por um nome seguido de um ou mais números inteiros. O objectivo é criar um novo ficheiro, deixando o antigo inalterado, adicionando no final de cada linha a soma dos números dessa linha. Valorizava-se uma solução em que as linhas no ficheiro eram reordenadas por ordem crescente das somas.
Solução:
A solução apresentada inclui o ordenamento das linhas. Para isso usamos o método itemgetter do módulo operator. Começamos por percorrer o ficheiro linha a linha, calculando a soma dos números e guardando o resultado numa lista. É feito o ordenamento da lista de seguida. Na terceira parte, criamos o novo ficheiro e guardamos a informação.
Solução:
A solução apresentada inclui o ordenamento das linhas. Para isso usamos o método itemgetter do módulo operator. Começamos por percorrer o ficheiro linha a linha, calculando a soma dos números e guardando o resultado numa lista. É feito o ordenamento da lista de seguida. Na terceira parte, criamos o novo ficheiro e guardamos a informação.
from operator import itemgetter
def trata_ficheiro(ficheiro,novo_ficheiro):
with open(ficheiro,'r') as f_in:
novos_dados = list()
for linha in f_in:
lista_linha = linha[:-1].split()
valor = sum([int(elem) for elem in lista_linha[1:]])
lista_linha.append(valor)
novos_dados.append(lista_linha)
novos_dados.sort(key=itemgetter(-1))
with open(novo_ficheiro,'w') as f_out:
for linha in novos_dados:
linha[-1] = str(linha[-1]) + '\n'
cadeia = ' '.join(linha)
f_out.write(cadeia)
return novos_dados
Teste Final - Pergunta 3
Guardamos num dicionário as classificações que diversos filmes receberam dos críticos (um valor entre 1 e 5). Queremos manter o dicionário actualizado e saber qual o filme com melhor pontuação média. Só podem ser candidatos a melhor filme os que tiverem pelo menos 3 valores.
Solução:
A solução abaixo usa o setdefault para actualizar o dicionário das classificações. Deste modo fica resolvida a questão de incluir uma primeira classificação ou simplesmente actualizar. Actualizado o dicionário, ele é percorrido, item a item, para determinar o melhor, prevendo o caso de não ter as 3 classificações.
Solução:
A solução abaixo usa o setdefault para actualizar o dicionário das classificações. Deste modo fica resolvida a questão de incluir uma primeira classificação ou simplesmente actualizar. Actualizado o dicionário, ele é percorrido, item a item, para determinar o melhor, prevendo o caso de não ter as 3 classificações.
def melhor_filme(filmes, classific):
# actualiza
nome = classific[0]
valores = classific[1:]
filmes[nome] = filmes.setdefault(nome,[]) + valores
# calcula melhor
m_filme = ''
m_pont = 0
for nome,pontos in filmes.items():
comp = len(pontos)
if comp < 3:
continue
media = (sum(pontos)/comp)
if media > m_pont:
m_filme = nome
m_pont = media
return (m_filme, m_pont)
Teste Final - Pergunta 2
Simular um jogo em que se atiram dardos a um alvo. No caso do teste o problema era mais simples pois não se pretendia simular o jogo mas apenas desenhar o alvo e simular o lançamento de um dardo. E fazer isto usando o módulo turtle. E construindo o programa de forma modular.
Vamos então dividir a solução em duas partes: uma para desenhar o alvo, e outra para simular o lançamento do dardo. Por outro lado, vamos fazer com que o desenho do alvo seja feito à custa de uma mesma função, a que desenha um círculo de uma dada cor, numa dada posição e com o dado raio. Essa função chama-se circunf. A partir dela desenhar o alvo é fácil (função alvo). Estas última precisa saber apenas o centro do alvo e o valor dos raios. Os cuidados a ter são desenhar as circunferências da maior para a mais pequena (notar o ordenamento inverso da lista dos raios), e controlar a alternância das cores.
O lançamento do dardo recorre ao módulo random para geral a posição, e ao comando dot para marcar a localização do dardo. Neste último caso, não conhecendo o comando dot, podia socorrer-se uma vez mais ao desenho de uma circunferência…
Vamos então dividir a solução em duas partes: uma para desenhar o alvo, e outra para simular o lançamento do dardo. Por outro lado, vamos fazer com que o desenho do alvo seja feito à custa de uma mesma função, a que desenha um círculo de uma dada cor, numa dada posição e com o dado raio. Essa função chama-se circunf. A partir dela desenhar o alvo é fácil (função alvo). Estas última precisa saber apenas o centro do alvo e o valor dos raios. Os cuidados a ter são desenhar as circunferências da maior para a mais pequena (notar o ordenamento inverso da lista dos raios), e controlar a alternância das cores.
O lançamento do dardo recorre ao módulo random para geral a posição, e ao comando dot para marcar a localização do dardo. Neste último caso, não conhecendo o comando dot, podia socorrer-se uma vez mais ao desenho de uma circunferência…
import turtle
def circunf(posx, posy, raio, cor):
# posiciona
turtle.pu()
turtle.goto(posx,posy-raio)
turtle.pd()
# define cor e desenha
turtle.fillcolor(cor)
turtle.begin_fill()
turtle.circle(raio)
turtle.end_fill()
turtle.hideturtle()
def alvo(posx, posy,raios):
"""
raios: lista dos raios dos discos
"""
raios.sort(reverse=True)
cor = 'black'
for raio in raios:
circunf(posx,posy,raio,cor)
if cor == 'black':
cor = 'white'
else:
cor = 'black'
def dardo():
import random
posx = random.randint(-100,100)
posy = random.randint(-100,100)
turtle.pu()
turtle.goto(posx,posy)
turtle.pd()
turtle.dot(8,'red')
turtle.hideturtle()
if __name__ == ‘__main__’:
alvo(0,0,[20,40,60,80])
dardo()
turtle.exitonclick()
Como se pode ver pelo código o programa é facilmente generalizável. Alvo de vários tamanhos (directo) e cores (passando as cores para argumentos), por exemplo.
Teste Final - Pergunta 1a
Pedia-se para dizer o que eram e para que serviam as excepções e as asserções. Por outro lado, também se pretendia saber as suas semelhanças e as suas diferenças, e ainda a apresentação de um exemplo concreto de cada.
De um modo geral excepções e asserções são formas de controlar possíveis erros ou verificar condições num programa.
As excepções são instruções de controlo, enquanto as asserções são instruções simples. As excepções permitem que o programa continue a ser executado, mesmo na presença de um erro, pois prevê acções de remediarão. No caso das asserções isso não acontece, pois o programa termina no caso da asserção não se verificar. Assim estas últimas são sobretudo usadas para depurar os programas.
As excepções são activadas (raise) quando durante a execução se verifica um erro. Os erros podem ser de diversos tipos, podendo as excepções ser genéricas ou dirigidas a um ou mais tipos de erro. Um exemplo simples e clássico é prevenir erros nas operações:
De um modo geral excepções e asserções são formas de controlar possíveis erros ou verificar condições num programa.
As excepções são instruções de controlo, enquanto as asserções são instruções simples. As excepções permitem que o programa continue a ser executado, mesmo na presença de um erro, pois prevê acções de remediarão. No caso das asserções isso não acontece, pois o programa termina no caso da asserção não se verificar. Assim estas últimas são sobretudo usadas para depurar os programas.
As excepções são activadas (raise) quando durante a execução se verifica um erro. Os erros podem ser de diversos tipos, podendo as excepções ser genéricas ou dirigidas a um ou mais tipos de erro. Um exemplo simples e clássico é prevenir erros nas operações:
def divisao_protegida(x,y): try: res = x/y return res except ZeroDivisionError: print(‘ERRO: divisão por zero’)No caso das asserções elas permitem verificar condições para que um programa possa correr. Um exemplo, também clássico, permite evitar um ciclo infinito:
def factorial(x): assert (x >=0), ‘ERRO: número negativo’ res = 1 while x: res *= x x -= 1 return res
Subscrever:
Mensagens (Atom)
