quinta-feira, 8 de janeiro de 2015

Teste Final - Pergunta 1b

A pergunta 1b do teste pedia para dizer, justificadamente, o que aparecia no lugar dos pontos de interrogação na sessão no interpretador seguinte:
>>> def xpto(x):
…    x += 1
…   print(x)
…   return
…
>>> x = 7
>>> print(xpto(x))
>>> ??? # —> 8
>>> ??? # —> None
>>> x
>>> ??? # —> 7
>>>
À frente dos pontos de interrogação colocámos o resultado real. Das respostas fica a certeza de que ainda existe muita confusão conceptual.

Vamos por partes.

Na sessão começamos por definir a função xpto. A função tem um parâmetro formal de nome x. O corpo da função consiste no incremento de uma unidade do parâmetro formal, seguido pela impressão do seu valor, terminando pela instrução de return, neste caso sem expressão associada.

De seguida associamos o nome x ao objecto 7.

Mandamos depois executar a função xpto passando como parâmetro real o nome x, pedindo ainda para imprimir o resultado da execução.

No final, queremos saber qual o valor associado ao nome x.

Que conceitos estão em jogo?

Desde logo o nome x fora da definição é uma variável do ambiente global, enquanto o parâmetro formal, com o mesmo nome x, é uma variável local à definição. Por outro lado, ao ser associado ao objecto 7, o nome x corresponde a um objecto imutável.

O que acontece quando mandamos executar a função xpto? É feita a passagem de parâmetros, que em Python significa que a identidade do x global (parâmetro real) é passada para o x local (parâmetro formal). Repito: a identidade! De seguida é executada a instrução x += 1. Como se trata de um objecto imutável as identidades do x global e do x local ficam diferentes. Os dois objectos, embora com o mesmo nome, estão guardados em zonas diferentes do espaço dos objectos!

Da execução de xpto resulta a instrução print(x) que vai imprimir o novo valor de x (local), ou seja 8.

Por outro lado, todas as funções devolvem sempre um resultado. Caso não exista return, ou a instrução de return não tenha uma expressão associada, o valor devolvido pela função é sempre o mesmo, o objecto None. Esse objecto é passado à instrução print que faz o que lhe compete, imprimindo … None.

Depois de executada a função xpto os nomes locais à definição (incluindo os parâmetros formais) deixam de estar associados a objectos. Independentemente disso, como já existia separação entre os objectos quando se tenta saber o valor do x “externo” o seu valor continua a ser o anteriormente definido, ou seja, 7. Isto tudo porque o objecto associado é imutável!!!

Portanto, a passagem de parâmetros não se faz por cópia, mas sim por passagem da identidade (referência) do parâmetro real ao parâmetro formal. Por outro lado não é o facto de uma variável ser global e outra local que explica o que aconteceu

Entendeu? Para tirar dúvidas veja o que acontece na situação seguinte:
>>> def xpto2(x):
…    x.append('a')
…    print(x)
…
>>> x = [1,2,3]
>>> print(xpto2(x))
[1, 2, 3, 'a']
None
>>> x
[1, 2, 3, ‘a']

Sem comentários:

Enviar um comentário