Introdução à programação e aos algoritmos

João Araujo Ribeiro · Capítulo 55 de 103

Páginas do PDF

Introdução à programação e aos algoritmos

4.5 Passagem de Parâmetros

Use o módulo random para simular o lançamento de um dado de 6 lados. Use a

função randint().

 

Fato 4.1 – Um programa não gera números aleatórios.

Um programa de computador é um mecanismo determinístico. Segue regras e desta

forma qualquer número gerado pela função random() ou semelhante não é

verdadeiramente aleatório.

O que acontece é que o número gerado tem um cálculo projetado de tal maneira

que não conseguimos descobrir a lógica de sua formação apenas observando a série

gerada. Desse modo, dizemos que o número gerado é pseudoaleatório. Normalmente

isto não é um problema, adequando-se perfeitamente às necessidades computacionais

desses números.

Existem maneiras de gerar números verdadeiramente aleatórios, mas esses

métodos se baseiam em algum mecanismo externo ao programa, em geral com um

hardware especial para isso.

A Intel, fabricante de chips de computador, produziu um mecanismo em hardware

de seus processadores para gerar números aleatórios, porém muitos programadores

rejeitam esse método por descon arem da segurança dos números gerados.

 

4.5 PASSAGEM DE PARÂMETROS

“Quando eu uso uma palavra”, disse Humpty Dumpty num tom bastante desdenhoso, “essa palavra significa exatamente o que quero que signifique: nem mais nem menos.”

“A questão é”, disse Alice, “se é possível fazer com que as palavras signifiquem tantas coisas diferentes.”

“A questão”, disse Humpty Dumpty, “é saber quem vai mandar – só isto.”

Lewis Carroll, Alice no País das Maravilhas

 

Uma função recebe informações que serão usadas para devolver um resultado. Essas informações são os parâmetros e são passadas por quem chama a função. Tanto pode ser o programa principal ou outra função. Esse mecanismo de enviar informações para uma função é chamado de passagem de parâmetros.

É importante entender como é feita a passagem de parâmetros em um programa de computador. Cada linguagem realiza esta tarefa segundo suas regras. As duas formas mais frequentes, nas linguagens de programação, são chamadas de “passagem por valor” e “passagem por referência”.

Python não se encaixa bem em nenhuma das duas.

Não importam muito os nomes que damos para as formas de passagem de parâmetros, o que importa é entender o que realmente ocorre. Entender como funciona a passagem de parâmetros evita muitas surpresas desagradáveis durante a execução de um programa.

No programa 4.13, o parâmetro de fatorial() é a variável n. Na linha 8 temos a chamada a fatorial(n). Neste momento você tem duas variáveis com o mesmo nome, n. Apesar de terem o mesmo nome, estas duas variáveis são entidades diferentes.

O que aconteceu então? Python faz a ligação de nomes com objetos. Para ilustrar melhor este conceito, veja o Programa 4.17.

1 def foo(n):

2 print(‘n - id:’, id(n), ‘valor:’, n, ‘em foo ‘)

3 n = 0

4 print(‘n - id:’, id(n), ‘valor:’, n, ‘em foo ‘)

5

6 n = 42

7 print(‘foo - id:’, id(foo))

8 print(‘n - id:’, id(n), ‘valor:’, n)

9 foo(n)

10 print(‘n - id:’, id(n), ‘valor:’, n)

 

■ Programa 4.17: Função Passagem de parâmetros.

 

Quando executado, o programa fornece a saída:

foo - id: 139624851768456

n - id: 10920736 valor: 42

n - id: 10920736 valor: 42 em foo

n - id: 10919392 valor: 0 em foo

n - id: 10920736 valor: 42

A função id() fornece o identificador de um objeto, ou seja,

grosso modo, uma identidade, um número associado ao objeto. O objeto, no caso, é o número 42, não a variável n. Como o nome de uma função também é um identificador, podemos usar id() para descobrir o objeto ao qual a função está associada. É uma informação em nível de máquina, mas que serve para demonstrar o que acontece quando você passa um parâmetro para uma função em Python. O resultado de id() vai ser diferente em cada computador e mesmo a cada vez que o programa for executado.

O que o programa está mostrando é o identificador de foo() e

de n para cada trecho do programa. A execução do programa mostra como o identificador de n muda.

Talvez ainda esteja confuso. É a primeira vez que vemos isso. A

Figura 4.9 ajuda a entender o que está acontecendo.

Figura 4.9 Pilha de execução do Programa 4.17.

 

Python faz a ligação de um nome de variável com um objeto na memória. Vamos analisar cada parte da figura.

Linha 6. No caso, na linha 6, Python liga o nome n ao identificador 10920736. Na área da memória referenciada por este identificador, está armazenado o valor 42. O identificador 10920736 é como um CPF ou endereço de 42, e indica de maneira única em que local está o número 42 na memória do computador. Nesse momento apenas a variável n está na pilha.

Linha 2. Quando for chamada a função foo(), o parâmetro n de foo() também estará ligado ao mesmo identificador de n anterior, 10920736; afinal essas variáveis se referem ao mesmo objeto de valor 42. A função chamada precisa saber em que ponto do programa deve retornar o fluxo de execução. Foi chamada quando o fluxo estava na linha 9. Isso vai para a pilha. As variáveis locais da função têm vida enquanto a função é executada; portanto, são temporárias. Essa informação também vai para a pilha. Uma pilha guarda dados de tal forma que, para liberar a área mais inferior, é preciso liberar antes a parte de cima, como uma pilha de pratos. Dessa forma, quando o fluxo de execução chega à linha 2, esta pilha de informações guarda a linha de retorno (9), a função chamada, foo(n), e o seu parâmetro, n. Estou abstraindo muitos detalhes para me concentrar no essencial.

Linha 3. Você se lembra de que um inteiro é um objeto imutável em Python? Quando é feita uma nova atribuição, na linha 3, o nome n passa a ser ligado a uma nova área de memória, portanto a um novo identificador: 10919392 com valor 0. O nome n original não foi modificado e permanece indicando o valor 42.

A Figura 4.9 mostra que quando o programa executa a linha 6, há apenas uma variável n que referencia o número 42. Quando a linha 2 é executada, ou seja, o início da função foo(), o valor de n, local a foo(), referencia o mesmo inteiro 42. Contudo, assim que é feita uma atribuição a n, este perde a ligação com o 42 original e vai referenciar o novo inteiro zero.