Skip to content
This page has been auto-translated and may contain errors.View in English

Variáveis e tipos ​

Todo programa precisa guardar informações. Um quiz precisa do nome do jogador. Um jogo precisa da pontuação atual. Um script de previsão do tempo precisa da cidade que você está consultando. O Python usa variáveis para isso: nomes que você associa a valores para poder usá-los ao longo do seu programa.

Variáveis são referências nomeadas a valores. O Python vincula um nome a um objeto no lado direito do = e permite que você o revincule a qualquer momento. O tipo pertence ao valor, não ao nome.

No Python, uma variável é uma vinculação de nome: um nome que aponta para um objeto (um objeto é qualquer valor que o Python guarda na memória, como uma string ou um número), nunca uma caixa rotulada que contém o próprio valor. O tipo pertence ao objeto, não ao nome, então um mesmo nome pode apontar para um str numa linha e para um int na linha seguinte sem erro nenhum. Essa liberdade se chama tipagem dinâmica: nada no nome limita para o que ele pode apontar.

python
player_name = "Alice"
score = 0
city = "Tokyo"

Três linhas, três coisas que o Python agora guarda na memória. Em cada uma, o Python primeiro calcula o valor do lado direito, e só então o armazena sob o nome do lado esquerdo. Use esse nome depois e o Python te devolve o valor.

Cada linha cria uma vinculação: o nome à esquerda se refere ao objeto à direita. O Python avalia o lado direito primeiro e só então cria a vinculação.

Cada atribuição vincula um nome no escopo atual (a região do código onde esse nome é visível, geralmente a função ou o arquivo em que você está trabalhando). O Python sempre calcula todo o lado direito antes de vincular qualquer coisa, e é exatamente por isso que a, b = b, a troca dois valores em uma única linha: o lado direito é totalmente calculado primeiro, e só depois os dois nomes são apontados para os resultados.

Armazenando um valor ​

O sinal = confunde quase todo mundo que vem da matemática escolar. No Python, = não significa "é igual a". Significa armazene este valor sob este nome:

python
city = "Tokyo"

city recebe "Tokyo". Você está dizendo ao Python: guarde "Tokyo" e rotule isso como city.

Você pode substituir o valor de uma variável a qualquer momento. O Python sempre usa o mais recente:

python
score = 0
score = 10   # score agora é 10
score = 15   # score agora é 15

= é atribuição: ela vincula um nome a um objeto no escopo atual. Um atalho padrão para atualizar uma variável é a atribuição composta:

python
score = 0
score += 10   # o mesmo que: score = score + 10
score *= 2    # o mesmo que: score = score * 2

Você também pode vincular vários nomes de uma vez:

python
x, y, z = 1, 2, 3
a = b = 0        # ambos começam em zero

A atribuição faz um nome apontar para um objeto; ela nunca copia o valor para um novo container. Assim, dois nomes podem acabar apontando exatamente para o mesmo objeto:

python
a = "hello"
b = a
print(id(a) == id(b))   # True (os dois nomes apontam para um único objeto)

b = "world"             # b passa a apontar para um novo objeto
print(id(a) == id(b))   # False
print(a)                # ainda "hello": revincular b não afetou a

id() retorna a identidade de um objeto, um número exclusivo daquele objeto enquanto ele existir, de modo que dois ids iguais significam "literalmente o mesmo objeto", não dois objetos que por acaso são iguais. É tentador ignorar a diferença entre apontar e copiar por enquanto, mas ela morde quando entram objetos mutáveis (aqueles que você pode alterar no próprio lugar, como listas): aponte dois nomes para uma mesma lista, altere-a por qualquer um dos dois nomes, e a alteração aparece nos dois. Listas e dicionários deixam isso bem concreto em capítulos mais adiante.

Uma anotação de tipo registra o tipo que você espera que um nome contenha. É uma anotação para ferramentas que leem seu código sem executá-lo (verificadores de tipo e seu editor), e o próprio Python a ignora enquanto o programa é executado:

python
name: str = "Alice"
score: int = 0
ratio: float = 0.85
JunoArmazenando um valor= não é o "igual" da aula de matemática, é "guarde este valor sob este nome". Mude quando quiser, e o Python mantém sempre o mais recente. Não precisa declarar nada, sem preparação: você dá o nome e ele já existe. Demorei tempo demais pra parar de complicar isso.
JunoArmazenando um valor= faz um nome apontar para um valor, e você pode reapontá-lo a qualquer momento. O nome é o rótulo, o valor é a coisa em si. É esse o truque todo.
JunoArmazenando um valor= não coloca um valor dentro de uma caixa, ele amarra um nome a um objeto. Reatribuir só move o nome; o objeto antigo continua onde estava. Lembre disso antes das listas aparecerem, ou você vai ter dois nomes compartilhando um mesmo objeto sem perceber.

Nomeando suas variáveis ​

Você escolhe o nome. O Python tem algumas regras rígidas, e a comunidade segue convenções que vale a pena adotar desde o primeiro dia. Nomes claros deixam o código legível semanas depois. Nomes obscuros causam dor de cabeça.

O Python impõe um pequeno conjunto de regras de sintaxe para identificadores. Além dessas, as convenções da PEP 8 são o padrão de fato em todo código Python e em toda ferramenta do ecossistema.

As regras que o Python de fato impõe para um identificador (o termo técnico para um nome) são minimalistas. O resto é a PEP 8, o guia oficial de estilo do Python. O interpretador (o programa que executa seu código) não a impõe, mas os linters (ferramentas que sinalizam problemas de estilo e bugs prováveis), os verificadores de tipo e todo código profissional esperam que você a siga. Ir contra ela geralmente só cria atrito para quem for ler seu código depois.

Regras que o Python impõe:

  • Apenas letras, dígitos e underscores. Sem espaços ou hifens.
  • Precisa começar com uma letra ou underscore, nunca com um dígito
  • Diferencia maiúsculas e minúsculas: score, Score e SCORE são três variáveis distintas

Convenções que todo mundo segue (PEP 8):

CoisaEstiloExemplo
Variáveis e funçõessnake_caseuser_name, total_price
ConstantesUPPER_SNAKE_CASEMAX_RETRIES, BASE_URL
ClassesPascalCaseUserAccount, DataLoader
python
# nomes claros, legíveis de imediato
user_name = "Alice"
total_price = 49.99
is_logged_in = True
MAX_RETRIES = 3

# você vai se arrepender destes em menos de uma hora
x = "Alice"
tp = 49.99
b = True

Uma armadilha que vale conhecer desde já: não dê a uma variável o nome de um recurso embutido do Python, como list, input, type ou print. O Python permite, mas você vai quebrar silenciosamente o recurso embutido pelo resto daquele escopo, e os erros resultantes são difíceis de rastrear.

Não sobreponha os recursos embutidos do Python. Atribuir a list, type, input, print ou str sobrescreve o recurso embutido pelo resto daquele escopo, sem nenhum aviso. É um bug silencioso que pode ser doloroso de encontrar.

UPPER_SNAKE_CASE é uma convenção, não uma regra imposta. O Python não vai te impedir de reatribuir MAX_RETRIES = 99 mais tarde. É apenas um sinal para outros desenvolvedores, nada além disso.

Sobrepor (shadowing) um recurso embutido significa criar seu próprio nome que coincide com algo que o Python já oferece (como list). Quando o Python procura um nome, ele checa os nomes locais antes dos seus próprios recursos embutidos, então sua versão prevalece e o list verdadeiro fica oculto a partir daquele ponto. Ele ainda é acessível como builtins.list, mas o código comum não o vê mais. Quanto às constantes, UPPER_SNAKE_CASE é só um sinal visual; o Python deixa você reatribuí-la sem problema. Se você quer uma constante que uma ferramenta consiga de fato impor, anote-a com typing.Final, que marca o nome como "não deve ser reatribuído", fazendo com que os verificadores de tipo sinalizem o erro se isso acontecer.

JunoNomeando suas variáveis Letras, números, underscores, e começando com uma letra ou underscore. Fique no snake_case e está tudo certo. Meu único erro de novato: não chamar uma variável de list ou print. O Python deixa, e depois tudo fica estranho sem nenhum aviso.
JunoNomeando suas variáveissnake_case para nomes, UPPER_SNAKE_CASE para constantes, toda ferramenta espera isso. E não dê nomes como list ou print às coisas, você vai atropelar o recurso embutido silenciosamente.
JunoNomeando suas variáveis O interpretador quase não impõe nada quanto a nomes, mas todo linter impõe, então brigar contra o snake_case só te traz dor de cabeça. A verdadeira armadilha é sobrepor um recurso embutido como list: quebra silenciosamente, e bem longe de onde você fez isso.

O que você pode armazenar ​

O Python tem quatro tipos que você vai usar em praticamente todo programa. O Python deduz qual tipo você quer dizer pela forma como você escreve o valor. Você nunca declara um tipo explicitamente.

O Python infere o tipo a partir da sintaxe do literal. Esses quatro tipos cobrem o espaço fundamental de valores; todo o resto da linguagem se constrói em cima deles.

Todo valor no Python é um objeto completo, até mesmo um literal (um valor escrito diretamente no código, como 42 ou "hi"). Ser um objeto significa que o valor traz consigo seus próprios métodos (funções ligadas a ele), então "hi".upper() e (3).bit_length() funcionam diretamente sobre o literal, sem nada para envolver ou desenvolver antes. Raramente você precisa pensar nisso, e esse é justamente o objetivo. Os quatro tipos abaixo são os que você usa em praticamente todo programa.

Texto (str) ​

Qualquer texto vai entre aspas, simples ou duplas. As aspas dizem ao Python que você quer caracteres literais, não o nome de uma variável. Depois de criada, uma string não pode ser alterada no próprio lugar. O capítulo Strings cobre tudo o que você pode fazer com elas.

python
player_name = "Alice"
city = "Tokyo"
message = 'Game over'

Se o seu texto contém um apóstrofo, use aspas duplas para não precisar escapá-lo:

python
note = "It's a great day"
note = 'It\'s a great day'   # mesmo resultado, usando um escape

Strings guardam qualquer texto entre aspas simples ou duplas. Elas são imutáveis: nenhuma operação modifica uma string no próprio lugar; toda transformação retorna uma string nova. Isso importa para desempenho: usar + repetidamente dentro de um loop cria um novo objeto string a cada passo. O capítulo Strings cobre a alternativa mais eficiente.

python
player_name = "Alice"
city = "Tokyo"
note = "It's a great day"

Uma str é uma sequência imutável de code points Unicode (imutável significa que ela nunca pode ser alterada depois de criada; code points são os próprios caracteres, não os bytes brutos em que eles acabam armazenados), e é por isso que len("café") é 4, não 5. Como uma string não pode mudar, ela é hashable e pode ser usada como chave de dicionário ou membro de um set (um valor que nunca muda pode ser catalogado com segurança pelo seu conteúdo). Uma regra que você vai realmente usar decorre disso: compare strings com == (mesmos caracteres), nunca com is (o mesmo objeto na memória), porque se duas strings iguais compartilham um único objeto é um detalhe de implementação em que você não pode confiar.

python
player_name = "Alice"
city = "Tokyo"
note = "It's a great day"
JunoTexto (str) Texto vai entre aspas, simples ou duplas, você escolhe. Depois de criada você não pode alterá-la no próprio lugar, e tudo bem. Qualquer coisa que pareça editar uma string na verdade te devolve uma string totalmente nova.
JunoTexto (str) Strings são imutáveis. Nada as edita no próprio lugar, você sempre recebe uma string nova de volta. Lembre disso na hora em que começar a encadear métodos.
JunoTexto (str) Uma sequência imutável de Unicode, então len("café") é 4 e strings funcionam como chaves de dicionário. O que você vai realmente usar: compare com ==, nunca com is.

Números inteiros (int) ​

Números inteiros entram sem aspas e sem ponto decimal. O Python os chama de inteiros (integers). Eles podem ser tão grandes quanto você precisar; o Python lida com números enormes sem nenhum esforço especial da sua parte.

python
score = 0
age = 28
population = 8_100_000_000   # underscores servem só para legibilidade

Inteiros são escritos sem aspas e sem ponto decimal. Os inteiros do Python têm precisão arbitrária: crescem para conter qualquer valor, ao contrário dos inteiros de tamanho fixo de 32 ou 64 bits em C ou Java. Underscores em literais numéricos são apenas cosméticos e o Python os ignora.

python
score = 0
age = 28
population = 8_100_000_000

Duas coisas vale a pena guardar. Primeiro, o int do Python tem precisão arbitrária: ele cresce para conter qualquer número inteiro que sua memória RAM comportar, então não há overflow (o estouro ou erro que acontece em linguagens com inteiros de tamanho fixo) para se preocupar. Segundo, compare números com == (valor igual), nunca com is (o mesmo objeto). Se dois inteiros iguais são o mesmo objeto é um detalhe de implementação: o CPython (o Python padrão) reaproveita inteiros pequenos, então id(1) == id(1) é True, mas isso deixa de valer silenciosamente para números maiores, então nunca conte com isso.

python
score = 0
age = 28
population = 8_100_000_000
JunoNúmeros inteiros (int) Números inteiros, sem aspas, sem ponto decimal. O melhor: os ints do Python crescem o quanto você quiser, sem overflow estranho. Aqueles underscores em 8_100_000_000 só estão lá para você conseguir ler.
JunoNúmeros inteiros (int) Ints têm precisão arbitrária, então overflow não é problema. Underscores em números são cosméticos, use em qualquer número com muitos dígitos.
JunoNúmeros inteiros (int) Ints crescem até acabar sua RAM, então overflow não é uma questão real. Um hábito que vale manter: compare números com ==, não com is. Identidade é uma peculiaridade de cache, não confie nela.

Números decimais (float) ​

Qualquer número com ponto decimal é um float. Eles funcionam como esperado na maioria dos cálculos. Uma coisa a saber: alguns valores decimais não podem ser armazenados de forma exata em binário, então você pode ter um pequeno erro de arredondamento:

python
price = 4.99
temperature = 36.6

0.1 + 0.2   # 0.30000000000000004

No dia a dia isso raramente importa. Para cálculos financeiros em que fração de centavo conta, o Python tem um módulo decimal que trata isso corretamente. Isso é abordado no capítulo Numbers.

Qualquer número com ponto decimal se torna um float. Os floats do Python têm precisão dupla: cerca de 15 a 17 dígitos significativos, armazenados em binário. Esse armazenamento em binário é a pegadinha conhecida: 0.1 + 0.2 dá 0.30000000000000004, o que não é um bug do Python, e sim uma consequência de como o binário representa decimais. Para dinheiro, ou em qualquer lugar em que decimais exatos importem, use o módulo decimal do Python, abordado no capítulo Numbers.

python
price = 4.99
temperature = 36.6

Floats são armazenados em binário (base 2), e a maioria das fracões decimais, tudo cujo denominador não é uma potência de dois (como 1/10), não pode ser escrita de forma exata em binário. É daí que vem o 0.1 + 0.2 resultando em 0.30000000000000004. A regra que importa em produção: nunca use um float para dinheiro, ou para qualquer coisa que você vá verificar por igualdade exata. Use decimal.Decimal quando precisar de aritmética decimal exata em base 10, ou fractions.Fraction para razões exatas. Ambos vêm com a biblioteca padrão do Python (as ferramentas que já acompanham o próprio Python), abordadas no capítulo Modules.

python
price = 4.99
temperature = 36.6
JunoNúmeros decimais (float) Um ponto decimal faz dele um float, e eles são tranquilos para uso do dia a dia. A pegadinha clássica que todo mundo pega uma vez: 0.1 + 0.2 resulta em 0.30000000000000004. Não é bug, isso é binário. Para dinheiro, use decimal.Decimal.
JunoNúmeros decimais (float) Floats são binários, então alguns decimais não ficam exatos, 0.1 + 0.2 não é exatamente 0.3. Tranquilo para a maioria das contas, nunca para dinheiro. Use decimal.Decimal quando precisar de exatidão.
JunoNúmeros decimais (float) Floats derivam, é por isso que 0.1 + 0.2 parece quebrado. A regra: nada de floats para dinheiro ou verificações de igualdade exata. decimal.Decimal para base 10 exata, fractions.Fraction para razões.

Verdadeiro ou falso (bool) ​

Algumas coisas estão ligadas ou desligadas. O Python usa booleanos para isso: exatamente dois valores, True e False. Eles parecem pouco importantes nesta fase, mas toda condição e todo desvio no seu programa se apoiam num booleano.

python
is_logged_in = True
has_errors = False

O Python também trata certos valores como se fossem False quando usados numa condição: 0, 0.0, "" e None (o "nenhum valor aqui" do Python) se comportam como False. Todo o resto se comporta como True. Isso se torna útil no capítulo Control flow.

bool guarda exatamente True ou False. É o que as comparações retornam e o que as condições consomem. O Python tem um conjunto mais amplo de valores truthy e falsy: valores zero, containers vazios e None são falsy; todo o resto é truthy. Um detalhe útil: bool é uma subclasse de int, então True + True resulta em 2.

python
is_logged_in = True
has_errors = False

bool é construído em cima de int (ele o subclassa, ou seja, é um tipo especializado de int), e True e False são os únicos dois objetos bool que existem, valendo exatamente 1 e 0. Numa condição, os valores falsy (os que contam como falso) são: zeros (0, 0.0), containers vazios ("", [], (), {}), None e o próprio False. Todo o resto é truthy. Suas próprias classes podem decidir sua veracidade definindo __bool__ ou __len__ (os métodos especiais "dunder", nomeados com underscores duplos, que o Python chama quando precisa de uma resposta de sim ou não). E, como um bool é um int, isinstance(True, int) é True, o que pode te pegar de surpresa em código que verifica tipos.

python
is_logged_in = True
has_errors = False
JunoVerdadeiro ou falso (bool) Dois valores, True e False, e eles estão por trás de todo if que você vai escrever. A parte divertida: 0, "", [] e None contam como False, todo o resto conta como True.
JunoVerdadeiro ou falso (bool)bool é o True/False que vem das comparações. O Python também tem truthy e falsy: coisas vazias, zero e None são falsy. É por isso que if my_list: lê tão bem.
JunoVerdadeiro ou falso (bool)bool é secretamente um int, então isinstance(True, int) é True, o que vai te surpreender numa verificação de tipo algum dia. Falsy é zeros, vazios e None. Objetos personalizados escolhem sua própria veracidade com __bool__ ou __len__.

Verificando e convertendo tipos ​

Quando você não tem certeza de qual é o tipo de um valor, type() te diz. Para verificar se um valor é de um tipo específico, isinstance() é a ferramenta mais confiável:

python
print(type("hello"))   # <class 'str'>
print(type(42))        # <class 'int'>
print(type(3.14))      # <class 'float'>
print(type(True))      # <class 'bool'>

isinstance(42, int)    # True
isinstance("hi", str)  # True

type() retorna o tipo exato de um objeto. Para verificação de tipo no seu próprio código, isinstance() é preferível: ela lida com herança, o que comparações usando type() não fazem.

python
print(type(42))          # <class 'int'>
isinstance(True, int)    # True   (bool é uma subclasse de int)
type(True) == int        # False  (só corresponde exatamente, sem subclasses)

type(x) te dá o tipo exato de x. isinstance(x, T) faz mais: ela percorre o MRO (a method resolution order, a lista ordenada de classes que o Python percorre subindo pela cadeia de herança, a linha de tipos-pai da qual uma classe é construída, exposta como x.__class__.__mro__), então ela também retorna True para tipos-pai. É por isso que isinstance(True, int) é True (um bool é um tipo de int) enquanto type(True) == int é False (uma verificação de correspondência exata). No código do dia a dia, use isinstance() como sua guarda de tipo (type guard), a verificação que confirma que um valor é do tipo esperado antes de você usá-lo.

python
isinstance(True, int)    # True
type(True) == int        # False

O Python não mistura tipos automaticamente. Concatenar uma string e um número gera um TypeError:

python
score = 42
print("Your score is " + score)        # TypeError
print("Your score is " + str(score))   # funciona

Converta explicitamente usando o nome do tipo como uma função:

ChamadaResultado
str(42)"42"
int(3.9)3 (truncado, não arredondado)
float("3.14")3.14
int("3.14")ValueError: não é possível converter uma string decimal para int diretamente
int(float("3.14"))3 (converta para float primeiro, depois para int)
bool(0) / bool("")False
JunoVerificando e convertendo tipostype() te diz o que uma coisa é, isinstance() verifica se ela é de um determinado tipo. E o Python não vai colar uma string e um número juntos, então converta primeiro com str() ou int(). Todo mundo cai nessa uma vez.
JunoVerificando e convertendo tipos Prefira isinstance() em vez de type() ==, ela respeita a herança. Conversões são sempre explícitas, então converta antes de concatenar uma string e um número.
JunoVerificando e convertendo tiposisinstance() é sua guarda de tipo, ela segue a árvore de classes, enquanto type(x) == T só corresponde exatamente. Conversões continuam explícitas de propósito, int("3.14") prefere gerar um erro a chutar, então passe por float primeiro.

Na prática ​

Os quatro tipos trabalhando juntos num script pequeno. As linhas de saída usam f-strings para embutir valores no texto: coloque f antes da aspa de abertura e envolva qualquer variável com {}. O Python a substitui pelo valor real da variável. Você vai aprender sobre elas de forma adequada no próximo capítulo.

python
player_name = "Alice"
level = 3
accuracy = 0.94
is_premium = True

print(f"{player_name} is on level {level} with {accuracy:.0%} accuracy.")
print(f"Premium account: {is_premium}")

Os tipos importam porque level + 1 funciona e player_name + 1 não. Cada variável guarda exatamente um tipo de coisa; o Python não vai misturá-las silenciosamente para você.

Um bloco de configuração realista com os quatro tipos, com as constantes separadas do estado em tempo de execução. A sintaxe f"..." é uma f-string: qualquer expressão dentro de {} é avaliada em tempo de execução e embutida na saída. Abordada por completo no capítulo Output and input.

python
BASE_URL = "https://api.example.com"
MAX_RETRIES = 3
DEBUG = False

user_name = "Alice"
request_count = 0
last_response = None

request_count += 1
print(f"[{request_count}] {BASE_URL} | debug={DEBUG}")

None é o marcador padrão para "ainda não há valor". Seu tipo é NoneType e ele se comporta como falsy em condições. Use-o como valor padrão para variáveis que só fazem sentido mais adiante no programa.

A mesma configuração, agora com anotações de tipo inline. Uma anotação registra o tipo que você espera que um nome contenha. Ela existe para verificadores de tipo e para o seu editor (a IDE), e o Python a ignora enquanto o programa é executado:

python
BASE_URL: str = "https://api.example.com"
MAX_RETRIES: int = 3
DEBUG: bool = False

user_name: str = "Alice"
request_count: int = 0
last_response: str | None = None

str | None é um tipo union, adicionado no Python 3.10: ele diz que o valor é uma string ou None. Em versões mais antigas, você escreve a mesma coisa como Optional[str], importado do módulo embutido typing. A forma str | None é a que você deve preferir no Python moderno sempre que sua versão mínima permitir.