Funções em Python - variáveis
Exemplo motivador
Uma função tem acesso a variáveis que foram criadas fora da função:
No exemplo, a função valor_final
usa a variável desconto
, que foi definida fora da função.
Agora insira uma linha de código no final do programa: print(multiplicador)
. O que aconteceu?
Note que fora da função não é possível acessar a variável multiplicador
. Por que isso acontece?
Escopo
Escopo de uma variável se refere à região de um programa que pode acessar uma variável.
No exemplo anterior:
- o escopo da variável
desconto
é o programa todo; ou seja, essa variável pode ser acessada em qualquer parte do programa, inclusive dentro de funções. - o escopo da variável
multiplicador
é apenas o corpo da funçãovalor_final
; fora da função ela não pode ser acessada
Dizemos também que cada função define um escopo, ou seja, uma região de código na qual as variáveis ali definidas podem ser acessadas.
Variáveis globais e locais
Variáveis globais são aquelas definidas fora de qualquer função. Após definidas, elas podem ser acessadas por qualquer parte do programa.
Variáveis locais são aquelas definidas dentro de uma função. Elas só podem ser acessadas dentro da função que a definiu.
No exemplo, dizemos que multiplicador
é uma variável local à função valor_final
.
Parâmetros são variáveis locais
Um parâmetro de função é uma variável local à função que é inicializado no momento em que a função é chamada.
No exemplo acima, quando a função valor_final
é chamada com o valor 10.0
, é criada uma variável preco
, local à função, que passa a referenciar o valor 10.0
. A seguir é executado o código da função.
Concluindo, na função valor_final
, as variáveis preco
e multiplicador
são locais; a variável desconto
é global.
Variável local mascara variável global de mesmo nome
Uma função pode definir uma variável local com o mesmo nome de uma variável global. Nesse caso dizemos que a variável local sombreia (ou mascara) a variável global.
Tente adivinhar a saída do código abaixo antes de executá-lo:
No exemplo, qualquer referência ao nome glob
dentro da função se refere à variável local glob
; qualquer referência feita fora da função se refere à variável global glob
.
Palavra-chave global
Em Python, se quisermos atribuir um novo valor a uma variável global, devemos usar a palavra-chave global
. Exemplo:
Note que, em geral, programadores não esperam que funções modifiquem variáveis globais, portanto use esse recurso com parcimônia para evitar surpresas.
Não complique
É importante saber todas essas regras da linguagem, mas, quando for escrever código, o melhor é não complicar. Assim:
- evite definir uma variável local com o mesmo nome de uma variável global
- evite atribuir um novo valor para um parâmetro; prefira criar uma outra variável
Evite variáveis globais
Variáveis globais tornam mais difícil a tarefa de compreender o que um programa faz. Considere novamente o exemplo:
desconto = 5
def valor_final(preco):
multiplicador = (100 - desconto) / 100
return preco * multiplicador
print(valor_final(10.0))
No exemplo, valor_final(10.0)
resulta no valor 9.5
.
Vamos supor que um amigo seu escreveu mais linhas de código no final do programa, de forma a atender a novas funcionalides. Em algum outro ponto do código, ele escreveu valor_final(10.0)
novamente. Pergunta: qual o resultado dessa chamada de função?
O resultado pode ser 9.5
novamente, mas, só olhando a linha de código que chama a função, não dá pra saber. Seu amigo pode ter mudado o valor da variável desconto
em algum momento antes de chamar a função:
desconto = 5
def valor_final(preco):
multiplicador = (100 - desconto) / 100
return preco * multiplicador
print(valor_final(10.0))
# ...
# ...
desconto = desconto * 2
# ...
# ...
print(valor_final(10.0))
Para ter certeza, é preciso rodar todo o programa, linha a linha, para determinar o valor da variável global desconto
no momento em que é feita a chamada a valor_final
.
Portanto, evite definir funções que dependam de variáveis globaisConstantes globais não são tão problemáticas. O problema é que Python não possui o conceito de constante..
O melhor a fazer nesse caso é passar como parâmetro todas as informações das quais a função depende:
def valor_final(preco, desconto):
multiplicador = (100 - desconto) / 100
return preco * multiplicador
Reatribuição de parâmetros
Considere o seguinte código:
Por que a variável numero
não mudou para 10
?
Quando realizamos a chamada troca_pelo_dobro(numero)
, o que está sendo passado como parâmetro é o número 5
, e a variável local x
passa a referenciar esse número. Ao executar x = x * 2
, x
passa a referenciar o número 10
. A variável número não é afetada.
Visualize a execução do código passo-a-passo.
Objetos mutáveis como parâmetro
Considere o seguinte código:
Por que lista
muda para [2, 4, 6]
enquanto numero
não se altera?
Observe que, em Python, objetos do tipo int
são imutáveis. A expressão x = x * 2
não modifica o número, e sim cria um novo número e faz x
referenciar esse novo número.
Já objetos do tipo list
são mutáveis. Em particular, a instrução l[i] = l[i] * 2
modifica a lista, fazendo a posição i
da lista referenciar um novo número. Como tanto l
quanto lista
referenciam a mesma lista, modificar o objeto referenciado por l
tem impacto sobre lista
.
Considere agora o código a seguir. Você sabe explicar por que ele não funciona?
Funções podem modificar objetos mutáveis que recebem como parâmetro, mas reatribuir um parâmetro dentro de uma função não altera a variável passada como parâmetro.