Programação

Escopo de variáveis: o que é e como funciona

Atualizado em

Capa do artigo Escopo de variáveis: o que é e como funciona
Leitura com foco

Entenda o contexto.
Leve para a prática.

Neste artigo
  1. O que é escopo de variáveis?
  2. O que é uma variável local?
  3. O que é uma variável global?
  4. Como o escopo funciona em Python, PHP e C?
  5. O que muda de uma linguagem para outra?
  6. Aí você pergunta: então é melhor deixar tudo global?
  7. Quais são os erros mais comuns com escopo?
  8. Agora é com você!

Escopo de uma variável é o trecho do programa em que ela existe e pode ser usada. Uma variável criada dentro de uma função é local: só vale ali dentro. Uma variável criada fora de todas as funções é global.

No artigo sobre funções, você viu que uma função é um pedaço de código com nome, que pode ser chamado quantas vezes você quiser. Faltou um detalhe: cada função tem o seu próprio quadrado, e as variáveis de dentro não se misturam com as de fora. E no artigo sobre atribuição, você viu como guardar um valor em uma variável. Hoje a pergunta é outra: onde essa variável vale?

Lembra da receita de bolo? Os ingredientes são as variáveis, e as ações (juntar, misturar, despejar) são as funções. Agora imagine uma cozinha de restaurante com várias bancadas. Cada cozinheiro tem os seus ingredientes na sua bancada, e um não mexe na tigela do outro. A despensa, lá no fundo, é de todos. A bancada é o escopo local. A despensa é o escopo global.

O que é escopo de variáveis?

É o conjunto de regras que define onde e quando uma variável pode ser usada. Ele também define o tempo de vida dela: uma variável global existe durante toda a execução do programa, e uma variável local só existe enquanto a função está sendo executada.

O escopo global com as variáveis mensagem e contador_global e, dentro dele, os escopos das funções mostrar, contar e somar_cinco com suas variáveis locais
As variáveis do programa deste artigo e o escopo de cada uma. Literalmente, é cada escopo no seu quadrado.

O que é uma variável local?

É a variável criada dentro de uma função. Ela nasce quando a função é chamada e some quando a função termina. Os parâmetros da função também são variáveis locais.

ATENÇÃO: uma variável local pode ter o mesmo nome de uma global. Nesse caso, dentro da função, a local esconde a global. São duas variáveis diferentes, e mexer em uma não muda a outra.

O que é uma variável global?

É a variável criada fora de todas as funções. Ela existe durante o programa inteiro, e por isso consegue guardar um valor entre uma chamada e outra de uma função. Compare os dois contadores do programa deste artigo: o local recomeça a cada chamada, e o global continua contando.

Ver a animação dos dois contadores em três chamadas
Animação de três chamadas da função: o contador local nasce com 0, vai a 1 e some, enquanto o contador global vai de 0 a 3
O contador local nasce com 0, vai a 1 e some no fim de cada chamada. O global passa por 1, 2 e 3.

Como o escopo funciona em Python, PHP e C?

Python:

# Escopo de variáveis: onde cada variável existe e pode ser usada

mensagem = "global"
contador_global = 0

def mostrar():
    mensagem = "local"      # outra variável, que só existe dentro da função
    print("Dentro da função: mensagem = %s" % mensagem)

def contar(chamada):
    global contador_global  # pede para usar a variável de fora
    contador_local = 0      # nasce de novo a cada chamada
    contador_local = contador_local + 1
    contador_global = contador_global + 1
    print("Chamada %d: contador local = %d, contador global = %d" % (chamada, contador_local, contador_global))

def somar_cinco(numero):
    numero = numero + 5     # muda só a cópia que a função recebeu
    print("Dentro da função: numero = %d" % numero)

mostrar()
print("Fora da função: mensagem = %s" % mensagem)

for chamada in range(1, 4):
    contar(chamada)

numero = 10
somar_cinco(numero)
print("Fora da função: numero = %d" % numero)

PHP:

<?php
// Escopo de variáveis: onde cada variável existe e pode ser usada

$mensagem = "global";
$contador_global = 0;

function mostrar(): void {
    $mensagem = "local";      // outra variável, que só existe dentro da função
    printf("Dentro da função: mensagem = %s\n", $mensagem);
}

function contar(int $chamada): void {
    global $contador_global;  // pede para usar a variável de fora
    $contador_local = 0;      // nasce de novo a cada chamada
    $contador_local = $contador_local + 1;
    $contador_global = $contador_global + 1;
    printf("Chamada %d: contador local = %d, contador global = %d\n", $chamada, $contador_local, $contador_global);
}

function somar_cinco(int $numero): void {
    $numero = $numero + 5;    // muda só a cópia que a função recebeu
    printf("Dentro da função: numero = %d\n", $numero);
}

mostrar();
printf("Fora da função: mensagem = %s\n", $mensagem);

for ($chamada = 1; $chamada <= 3; $chamada++) {
    contar($chamada);
}

$numero = 10;
somar_cinco($numero);
printf("Fora da função: numero = %d\n", $numero);

C:

/* Escopo de variáveis: onde cada variável existe e pode ser usada */
#include <stdio.h>

const char *mensagem = "global";
int contador_global = 0;

void mostrar(void) {
    const char *mensagem = "local";  /* outra variável, que só existe dentro da função */
    printf("Dentro da função: mensagem = %s\n", mensagem);
}

void contar(int chamada) {
    int contador_local = 0;          /* nasce de novo a cada chamada */
    contador_local = contador_local + 1;
    contador_global = contador_global + 1;  /* em C, a função enxerga a variável de fora */
    printf("Chamada %d: contador local = %d, contador global = %d\n", chamada, contador_local, contador_global);
}

void somar_cinco(int numero) {
    numero = numero + 5;             /* muda só a cópia que a função recebeu */
    printf("Dentro da função: numero = %d\n", numero);
}

int main(void) {
    mostrar();
    printf("Fora da função: mensagem = %s\n", mensagem);

    for (int chamada = 1; chamada <= 3; chamada++) {
        contar(chamada);
    }

    int numero = 10;
    somar_cinco(numero);
    printf("Fora da função: numero = %d\n", numero);
    return 0;
}

Saída:

Dentro da função: mensagem = local
Fora da função: mensagem = global
Chamada 1: contador local = 1, contador global = 1
Chamada 2: contador local = 1, contador global = 2
Chamada 3: contador local = 1, contador global = 3
Dentro da função: numero = 15
Fora da função: numero = 10

Foque no conceito, e não na linguagem! Cada função mostra uma regra:

  • mostrar: cria uma variável local chamada mensagem. A global com o mesmo nome continua valendo “global” depois da chamada.
  • contar: o contador local dá 1 nas três chamadas, porque nasce de novo a cada vez. O contador global chega a 3.
  • somar_cinco: o parâmetro é uma cópia. Dentro da função ele vira 15, e a variável de fora continua com 10.

O que muda de uma linguagem para outra?

A ideia de escopo é a mesma nas três, mas as regras têm diferenças que pegam muita gente. Repare que o programa em Python e o programa em PHP têm uma linha com a palavra global, e o programa em C não tem. Testei quatro situações:

Tabela comparando quatro situações de escopo em Python, PHP e C, como ler e alterar uma variável de fora dentro da função
O PHP não enxerga a variável de fora sem a palavra global. O C trata o bloco do for como um escopo.
  • Ler, dentro da função, uma variável de fora: o Python leu o valor 10, e o C também lê. O PHP não enxergou: mostrou “Warning: Undefined variable $valor”.
  • Alterar, dentro da função, uma variável de fora: o C altera direto. No Python, sem a linha global, o programa parou com “UnboundLocalError: cannot access local variable ‘contador’ where it is not associated with a value”. No PHP, sem a linha global, saiu um aviso e o contador de fora continuou em 0.
  • Usar fora uma variável criada dentro da função: o Python parou com “NameError: name ‘valor’ is not defined”. O PHP mostrou “Warning: Undefined variable $valor”. O GCC nem compilou: “‘valor’ undeclared”.
  • Usar depois do for uma variável criada dentro dele: no Python e no PHP, ela ainda existia depois do laço. No C, o GCC recusou com “‘i’ undeclared”: ali, o bloco entre chaves também é um escopo.

Aí você pergunta: então é melhor deixar tudo global?

Não. Parece mais fácil, mas uma variável global pode ser alterada por qualquer parte do programa, e fica difícil descobrir quem mudou o quê. Além disso, uma função que depende de uma variável de fora só funciona se essa variável existir. O caminho mais seguro é o que você viu na função somar_cinco: o que a função precisa entra pelo parâmetro. E o que ela produz sai pelo retorno.

Quais são os erros mais comuns com escopo?

  • Usar fora da função uma variável criada dentro dela. Fora da função, ela não existe.
  • No PHP, esperar que a função enxergue a variável de fora. Sem a palavra global ou sem um parâmetro, ela não enxerga.
  • No Python, alterar uma variável global sem declarar global. O programa para com UnboundLocalError.
  • Achar que mudar o parâmetro muda a variável original. O numero virou 15 dentro da função e continuou 10 fora.
  • Dar o mesmo nome a uma local e a uma global e esquecer que são duas. Foi o caso da variável mensagem.
  • Esperar que a variável local lembre do valor da chamada anterior. O contador local deu 1 nas três chamadas.
  • No C, usar depois do laço a variável declarada no for. Ela só existe dentro do laço.

Agora é com você!

No papel:

  • Um programa tem a variável global total valendo 100. Uma função cria uma variável local total valendo 5 e mostra o valor. Depois da chamada, o programa mostra total. Quais são os dois valores mostrados?
  • Uma função recebe o parâmetro preco, soma 10 a ele e termina. Fora dela, a variável preco valia 50. Quanto vale depois da chamada?
  • No programa do artigo, o que apareceria na coluna do contador global se a função contar fosse chamada 5 vezes?

No computador:

  • Reescreva a função contar sem usar variável global: receba o valor atual por parâmetro e devolva o valor novo.
  • Crie duas funções com uma variável local de mesmo nome em cada uma e confirme que uma não interfere na outra.
  • Tire a linha global da função contar, na linguagem que você estiver usando, e leia a mensagem que aparece.

Tente sozinho, sem pedir a resposta pronta para ninguém, nem para a IA!

No próximo artigo, o assunto é repetir coisas: o laço for. Até lá!

Confiança Sempre!!!

Fontes:

Sobre quem escreve

Walmir Silva

Olá! Sou Walmir, engenheiro de software com MBA em Engenharia de Software e o cérebro por trás do GrowthCode e autor do livro "Além do Código".

Se você acha que programação é apenas sobre escrever código, prepare-se para expandir seus horizontes. Aqui, nós vamos além do código e exploramos as interseções fascinantes entre tecnologia, negócios, artes e filosofia.

Você está em busca de crescimento na carreira? Quer se destacar em um mercado competitivo? Almeja uma vida mais rica em conhecimento e realização? Então você chegou ao lugar certo. No GrowthCode, oferecemos insights profundos, estratégias comprovadas e um toque de sabedoria filosófica para catalisar seu crescimento pessoal e profissional.

Ver todos os artigos →

Continue a conversa

Compartilhe sua perspectiva

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Encontre sua próxima resposta

O que você quer aprender?

Preferências de cookies

Os cookies opcionais começam desligados. Você pode mudar a escolha a qualquer momento por esta tela.

NecessáriosSempre ativos

Guardam a sua escolha de cookies e mantêm o site funcionando. Não são usados para publicidade.

Contam visitas e mostram como o site é usado: Google Analytics e Microsoft Clarity, carregados pelo Google Tag Manager. Como esse contêiner também carrega tags de publicidade, as estatísticas só são ativadas junto com Publicidade e marketing.

Exibem anúncios do Google AdSense e medem campanhas e e-mails: pixels da Meta e do TikTok e o Mautic.

Permite que o Google escolha anúncios com base nos seus interesses. Desligado, os anúncios aparecem sem personalização. Depende de Publicidade e marketing.

Também é possível bloquear cookies nas configurações do navegador. Detalhes na Política de privacidade.