sexta-feira, 26 de janeiro de 2018

Exame Recurso - Pergunta 2

Como se pode usar o turtle para desenhar figuras como:
Devia ser possível fazer variar diversos parâmetros, como o número de arcos, o raio, a cor, a posição. Solução é relativamente trivial:
01.import turtle as tt
02. 
03.def bolachas(n, raio, orienta=0, posx=0,posy=0,cor='red'):
04.    # inicializa
05.    tt.penup()
06.    tt.setheading(orienta)
07.    tt.goto(posx,posy)
08.    tt.color(cor)
09.    tt.begin_fill()
10.    tt.pendown()
11.    ang = 180 - (360/n)
12.    for i in range(n):
13.        tt.circle(raio,180)
14.        tt.right(ang)
15.    tt.end_fill()
16.    tt.hideturtle()
17.     
18.     
19.if __name__ == '__main__':
20.    n= 30
21.    raio=25
22.    orienta = 45
23.    posx = 100
24.    posy = 100
25.    cor = 'blue'
26.    bolachas(n, raio, orienta, posx,posy,cor)
27.    tt.exitonclick()
Como se pode ver pela solução, a opção foi a de desenhar semi-circunferências. A única questão relevante, mais complexa, era perceber como rodar a tartaruga após o desenho de cada arco. Como se pode no código acima ver tal está relacionado com o número de arcos.

Exame Recurso - P1

No exame de recurso era apresentada a seguinte sessão no interpretador:
1.>>> def teste(x):
2....    def mist(y):
3....        return x**y
4....    return mist
5....
6.>>> oops = teste(2)
7.>>> oops(4)
8.16
e perguntava-se para explicitar o que se tinha passado.

As respostas demonstram a grande confusão conceptual que ainda existe. Mas vamos por partes. A sessão pode ser dividida em três partes. Na primeira, é definida uma função (teste) cujo corpo é formado pela definição de outra função (mist). A função teste devolve como resultado a função mist. Na segunda, é feita a atribuição
1.oops = teste(2)
Em Python, todas as atribuições são do tipo:
1.nome = expressão
Assim o que vai acontecer é que é calculado o valor associado à expressão teste(2) e esse valor é um novo objecto de nome … nome! No nosso caso, a expressão vai ter como valor um objecto do tipo função que devolve 2**y, que tem oops como um atributo do tipo nome. Na terceira parte, essa nova função é chamada com o argumento igual a 4, pelo que o resultado que se obtém será 2**4 = 16.

A sessão abaixo ilustra o que acabámos de dizer.
01.>>> id(teste)
02.4504739912
03.>>> type(oops)
04.<class 'function'="">
05.>>> id(oops)
06.4504740048
07.>>> dir()
08.['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'oops', ‘teste']
09.</class>
Como use pode ver, no espaço de nomes apenas são conhecidos oops e teste. Sao ambos nomes associados a funções distintas. Podemos expandir as coisas recorrendo ao módulo inspect.
01.>>> import inspect
02.>>> inspect.getargspec(oops)
03.ArgSpec(args=['y'], varargs=None, keywords=None, defaults=None)
04.>>> inspect.getargspec(teste)
05.ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
06.>>> inspect.getclosurevars(oops)
07.ClosureVars(nonlocals={'x': 2}, globals={}, builtins={}, unbound=set())
08.>>> inspect.getclosurevars(teste)
09.ClosureVars(nonlocals={}, globals={}, builtins={}, unbound=set())
Como notamos, cada uma das funções tem o seu argumento (x, para teste, y, para oops), mas oops tem x como variável não local instanciada a 2!