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

Strings

Texto aparece em quase todo programa que você escreve. Nomes, mensagens, pontuações, rótulos. Em Python, qualquer trecho de texto é chamado de string: qualquer valor envolvido por aspas. Simples ou duplas, ambas funcionam da mesma forma.

Strings são o tipo principal de texto do Python. Carregam tudo, desde um nome de usuário até um caminho de URL ou uma saída formatada. Aspas simples e duplas produzem resultados idênticos; a escolha é estilística.

str é o tipo de sequência Unicode imutável do Python. Está presente em todas as fronteiras do sistema: I/O de terminal, conteúdo de arquivos, respostas de rede, dados serializados. Os dois estilos de aspas produzem o mesmo objeto; o tokenizador os trata de maneira idêntica.

python
greeting = "Hello, world"
username = 'alice'

A única vez em que a escolha das aspas importa é quando seu texto contém aspas. Use o estilo oposto para não precisar escapá-las:

A convenção da comunidade é usar aspas duplas. O motivo prático para trocar de estilo é evitar o escape quando o conteúdo contém esse caractere:

A convenção é usar aspas duplas. O único motivo para trocar é evitar um escape com barra invertida quando o conteúdo contém esse delimitador:

python
note    = "It's a great day"      # apóstrofo dentro, use aspas duplas
message = 'She said "hello"'      # aspas duplas dentro, use aspas simples
escaped = "She said \"hello\""    # ou escape com uma barra invertida

Imutabilidade

Strings são imutáveis: depois de criada, você não pode alterá-la. Pense em uma string como permanentemente fixa no momento em que é feita. Qualquer operação que pareça modificá-la, na verdade, produz uma nova. A original permanece exatamente como estava.

Strings são imutáveis: nenhum método modifica uma string no lugar. Toda operação que transforma texto retorna uma nova string e deixa a original intacta. A consequência prática é que uma chamada de método cujo resultado você não atribui a lugar nenhum não tem efeito sobre nada.

Objetos str são imutáveis: o buffer interno é fixado na construção e não pode ser sobrescrito. Isso dá às strings três propriedades úteis: são hasháveis (válidas como chaves de dict e membros de set), seguras para compartilhar entre referências sem cópia, e elegíveis para a otimização de interning do CPython em literais curtos.

python
name = "alice"
name = name.upper()   # "ALICE" é uma nova string; "alice" permanece inalterada

A consequência direta: você não pode alterar um caractere em uma posição específica. Python vai gerar um erro se você tentar.

python
name = "alice"
name[0] = "A"   # TypeError: 'str' object does not support item assignment

Para obter uma string modificada, construa uma nova usando fatiamento ou um método. Ambos são abordados abaixo.

Tentar atribuir um caractere mostra a restrição diretamente:

python
name = "alice"
name[0] = "A"   # TypeError: 'str' object does not support item assignment

Quando você precisa de uma versão modificada, as ferramentas padrão são o fatiamento com concatenação para edições posicionais, e replace() para substituições. Ambas produzem uma nova string e deixam a original intacta.

str.__setitem__ não é implementado; a atribuição por item gera TypeError incondicionalmente. Para modificação posicional, use fatiamento: name[:1].upper() + name[1:]. Para substituição, replace(). Para montar muitos pedaços, "".join(parts) é importante: s += chunk repetido dentro de um laço é O(n²), pois cada + aloca um novo buffer do tamanho combinado e copia ambos os operandos para dentro. join() aloca uma única vez.

Indexação e fatiamento

Cada caractere em uma string tem uma posição numerada, começando do zero. Você pode ler caracteres individuais colocando esse número de posição entre colchetes. Números negativos contam de trás para frente, a partir do final.

Strings são sequências com indexação baseada em zero. Índices negativos contam a partir do final. O fatiamento extrai qualquer intervalo contíguo em uma única expressão, e nunca gera erro para valores fora do intervalo.

str implementa o protocolo de sequência completo. Acesso por subscrito (s[i]) passa por __getitem__ com um inteiro e gera IndexError para entradas fora do intervalo. O fatiamento (s[start:stop:step]) passa um objeto slice; os índices são silenciosamente limitados a um intervalo válido, então nenhum IndexError é possível a partir de um fatiamento.

python
word = "Python"
#       012345

print(word[0])    # "P"
print(word[2])    # "t"
print(word[5])    # "n"
print(word[-1])   # "n"  (último caractere)
print(word[-2])   # "o"  (penúltimo)

-1 é sempre o último caractere, -2 o penúltimo, e assim por diante. São úteis quando você quer o final de uma string sem saber o tamanho exato.

Índices negativos dão a volta: -1 é len(s) - 1, -2 é len(s) - 2. Mais úteis para acesso ancorado ao final, quando você não quer calcular o tamanho manualmente. Um índice negativo que sai do intervalo ainda gera IndexError, igual a um positivo.

Índices negativos são normalizados para len(s) + i antes da verificação de limites. Não há um tratamento especial no interpretador; é aritmética. Fora do intervalo gera IndexError independente do sinal.

Fatiamento extrai um pedaço. [start:stop] inclui start e exclui stop:

python
word = "Python"

print(word[0:2])   # "Py"     (posições 0 e 1)
print(word[2:])    # "thon"   (posição 2 até o fim)
print(word[:3])    # "Pyt"    (início até a posição 2)
print(word[:])     # "Python" (uma cópia da string inteira)
print(word[::2])   # "Pto"    (cada segundo caractere)
print(word[::-1])  # "nohtyP" (invertida)

Três padrões para ter em mente: word[:n] para os primeiros n caracteres, word[n:] para tudo a partir da posição n, word[-n:] para os últimos n caracteres. word[::-1] inverte uma string. Parece estranho da primeira vez, mas é Python idiomático e você vai vê-lo com frequência.

Diferente da indexação direta, o fatiamento nunca gera IndexError. Python limita silenciosamente os índices fora do intervalo, então word[100:] em uma string curta retorna "" em vez de falhar. O argumento step controla o passo: word[::2] pega um caractere a cada dois, word[::-1] percorre ao contrário.

s[start:stop:step] passa slice(start, stop, step) para __getitem__. Os três argumentos têm padrão None, não 0 e len(). Com um step negativo, os padrões se invertem: start passa a ser len - 1, stop passa a ser -(len + 1). É isso que faz com que [::-1] percorra a string inteira ao contrário sem nenhum limite explícito.

Métodos essenciais de string

Strings vêm com um conjunto de métodos embutidos: operações que você chama diretamente em qualquer valor de string. Você escreve a string (ou a variável que a contém), depois um ponto, depois o nome do método. Cada método retorna uma nova string. A original nunca é alterada.

Métodos de string são funções vinculadas ao tipo str. Como strings são imutáveis, todo método retorna uma nova string em vez de modificar a original. Uma chamada de método cujo resultado você não atribui ou passa para outro lugar não tem efeito duradouro.

Os métodos de str são definidos no objeto de tipo e implementados em C. Todos os métodos de transformação seguem o contrato de imutabilidade: retornam novos objetos str. A implementação do CPython é totalmente compatível com Unicode; os métodos operam sobre code points, não sobre bytes.

Caixa

python
text = "Hello, World"

text.lower()       # "hello, world"
text.upper()       # "HELLO, WORLD"
text.title()       # "Hello, World"  (cada palavra em maiúscula)
text.capitalize()  # "Hello, world"  (apenas a primeira palavra)

lower() e upper() são os dois que você mais vai usar. lower() é particularmente útil ao comparar textos: "Alice" e "alice" se tornam a mesma coisa depois de chamar .lower() em ambos os lados.

lower() é o passo padrão de normalização antes de comparação ou armazenamento. title() coloca a primeira letra de cada palavra em maiúscula usando uma regra simples que falha em contrações: "it's" vira "It'S". Trate-o como formatação apenas para exibição.

lower() aplica a conversão de caixa Unicode completa. Para comparação insensível a caixa, casefold() é mais correto: aplica transformações adicionais (por exemplo, ß em alemão vira ss) que o lower() pula. title() coloca em maiúscula após qualquer caractere não alfanumérico, o que trata mal contrações e nomes com hífen. Para casamento de título correto, implemente a lógica manualmente.

Espaços em branco

python
text = "  hello  "

text.strip()    # "hello"    (ambos os lados)
text.lstrip()   # "hello  "  (apenas à esquerda)
text.rstrip()   # "  hello"  (apenas à direita)

strip() remove espaços de ambas as pontas de uma string. Você vai usá-lo praticamente toda vez que lidar com entrada do usuário ou texto vindo de um arquivo, porque espaços perdidos causam falhas silenciosas: "alice" != "alice ".

strip() remove todos os espaços em branco no início e no fim: espaços, tabs e quebras de linha. As variantes direcionais permitem limpar apenas um lado, útil para remover uma quebra de linha final sem mexer na indentação. Os três aceitam um argumento opcional de caracteres para remover caracteres específicos.

strip() sem argumentos remove caracteres para os quais str.isspace() retorna True, um conjunto compatível com Unicode que inclui espaços em branco não-ASCII. Com um argumento de caractere, ele remove qualquer caractere desse conjunto de ambos os lados (uma checagem de pertencimento de caractere, não uma correspondência de prefixo). "xxhelloxx".strip("x") retorna "hello". Argumentos com múltiplos caracteres removem qualquer um deles individualmente, o que é uma fonte comum de bugs sutis.

Busca

python
text = "Hello, world"

text.find("world")         # 7
text.find("Python")        # -1  (não encontrado)
text.count("l")            # 3
text.startswith("Hello")   # True
text.endswith("world")     # True

find() retorna a posição onde um trecho de texto começa dentro da sua string. Se não estiver lá, retorna -1. Use startswith() e endswith() quando você só se importar se a string começa ou termina com algo específico.

find() retorna o índice de início da primeira ocorrência, ou -1. A convenção do -1 permite usar o resultado diretamente em fatiamento ou aritmética sem uma checagem. startswith() e endswith() aceitam uma tupla de strings, facilitando testar múltiplos prefixos ou sufixos em uma única chamada.

find() é uma varredura linear da esquerda para a direita, O(n*m) no pior caso. index() é idêntico, mas gera ValueError quando não há correspondência: use index() quando a ausência for um erro de programação, find() quando for entrada esperada. startswith() e endswith() fazem curto-circuito ao primeiro descasamento e são mais rápidos que uma checagem com find() ou in para testes de prefixo/sufixo.

Substituição

python
text = "Hello, world"

text.replace("world", "Python")   # "Hello, Python"
text.replace("l", "L")            # "HeLLo, worLd"  (todas as ocorrências)
text.replace("l", "L", 1)         # "HeLlo, world"  (apenas a primeira)

replace() troca cada ocorrência de um trecho por outro e te devolve uma nova string. A original não é alterada. Passe um terceiro argumento se quiser substituir apenas a primeira ocorrência.

replace() substitui todas as ocorrências não sobrepostas por padrão. O argumento count limita quantas serão substituídas. Como retorna uma nova string, as chamadas podem ser encadeadas: text.replace("a", "A").replace("e", "E") aplica as duas substituições em sequência.

replace() realiza uma varredura literal de substring e constrói o resultado em uma única alocação quando não há count; com um count ele para antes. Para substituição baseada em padrões, o módulo re do Python é a ferramenta adequada. Isso é abordado no capítulo de Módulos.

Divisão e junção

split() corta uma string em pedaços em um separador e os retorna como uma lista. Você diz onde cortar:

split() particiona em um separador e retorna os segmentos como uma lista. Chamado sem argumento, divide em qualquer sequência de espaços em branco e descarta strings vazias geradas por múltiplos espaços consecutivos:

split(sep) varre da esquerda para a direita, dividindo a cada ocorrência não sobreposta de sep. Sem argumento, usa um algoritmo diferente: divide em qualquer sequência de espaços em branco e remove os espaços em branco do início e do fim do resultado. rsplit(sep, n) divide a partir da direita, útil para isolar o último segmento de um caminho pontuado ou identificador com namespace:

python
csv_row = "Bruno,28,Brasília"
parts = csv_row.split(",")     # ["Bruno", "28", "Brasília"]

"  hello   world  ".split()   # ["hello", "world"]

O que é uma lista?

Uma lista é uma coleção ordenada de valores. ["Bruno", "28", "Brasília"] acima é uma. Listas terão seu próprio capítulo; por enquanto, trate-as como uma sequência de itens que split() produz e join() consome.

join() faz o inverso: combina uma lista de strings em uma só. A string antes de .join() é colocada entre cada item:

python
words = ["Hello", "world"]

" ".join(words)    # "Hello world"
", ".join(words)   # "Hello, world"
"".join(words)     # "Helloworld"

O padrão a lembrar: separator.join(list_of_strings). O separador vai à esquerda, a lista à direita. " ".join(words) coloca um espaço entre cada palavra. "".join(words) cola as palavras sem nada entre elas.

join() é a ferramenta certa sempre que você está montando uma única string a partir de várias partes. Ele realiza uma única alocação em vez de criar uma nova string a cada passo. Para duas ou três strings, + é perfeitamente válido. Quando você tem uma lista de tamanho significativo, recorra a join().

join() é O(n): chama __iter__ uma vez, calcula o tamanho total necessário em uma passagem, realiza uma única alocação e então escreve cada pedaço e o separador diretamente no buffer. O + repetido é O(n²): cada operação aloca um novo buffer do tamanho combinado e copia ambos os operandos para dentro. O CPython tem uma otimização limitada para += repetido em uma única variável local, mas é frágil entre refatorações e não é garantida. join() é sempre correto e sempre rápido.

f-strings

f-strings embutem valores diretamente dentro do texto. Coloque f antes das aspas de abertura, depois envolva qualquer variável ou expressão em chaves. O Python preenche tudo quando o código é executado. Você também pode adicionar dois pontos após o valor para controlar como ele é exibido.

f-strings avaliam qualquer expressão dentro de {} em tempo de execução e convertem o resultado em string. Dois pontos dentro das chaves introduzem uma especificação de formato: uma sintaxe compacta para controlar casas decimais, alinhamento e formatação de números.

f-strings (PEP 498) compilam cada expressão {} em bytecode que chama format(value, spec), que delega para value.__format__(spec). Qualquer classe que implemente __format__ controla sua própria exibição dentro de uma f-string. Os flags de conversão !r, !s, !a aplicam repr(), str() ou ascii() antes da chamada de formatação.

python
name  = "Bruno"
score = 94.5

print(f"Hello, {name}!")           # "Hello, Bruno!"
print(f"Score: {score:.1f}%")      # "Score: 94.5%"
print(f"2 + 2 = {2 + 2}")          # "2 + 2 = 4"
print(f"Name: {name.upper()}")     # "Name: BRUNO"

A especificação de formato após : controla como o valor é exibido:

SpecSignificadoExemplo
.2f2 casas decimaisf"{3.14159:.2f}""3.14"
.0%porcentagem, sem decimaisf"{0.94:.0%}""94%"
,separador de milharesf"{1000000:,}""1,000,000"
>10alinhar à direita em 10 charsf"{'hi':>10}"" hi"

Você vai usar .2f mais vezes: sempre que exibir um decimal e quiser um número arrumado em vez de uma longa sequência de dígitos. Todo o resto na tabela está lá para quando você precisar. Você pode colocar qualquer variável, aritmética ou chamada de método dentro do {}.

.2f e .0% cobrem a maior parte da formatação de exibição. Os especificadores de alinhamento (>, <, ^) produzem saída tabular quando combinados com uma largura. O padrão geral é {value:[align][width][.precision][type]}. Uma vez que você reconhece as partes, qualquer spec é legível sem precisar memorizar todas as combinações.

A spec é passada literalmente para __format__; os tipos embutidos a tratam em C. !r é o flag de conversão mais útil: chama repr() antes da formatação, o que adiciona aspas em torno de strings e torna caracteres invisíveis (tabs, espaços no final, quebras de linha) visíveis como sequências de escape. Classes personalizadas podem implementar __format__ para aceitar strings spec arbitrárias e produzir qualquer saída.

Strings multilinha

Para escrever uma string que abrange mais de uma linha, use aspas triplas: três " no início e três no fim. O Python preserva todas as quebras de linha e o espaçamento exatamente como você escreveu.

Strings entre aspas triplas preservam todo o espaçamento e quebras de linha literalmente. São padrão para blocos longos de texto, como modelos de e-mail e consultas SQL, e para docstrings: a documentação inline colocada no início do corpo de uma função ou classe.

Literais entre aspas triplas preservam todos os caracteres literalmente, incluindo os espaços em branco no início de cada linha. Quando usados como a primeira instrução no corpo de uma função, classe ou módulo, o Python armazena a string como o atributo __doc__ desse objeto. Ferramentas como help() exibem isso; o espaço em branco inicial é tipicamente removido por textwrap.dedent(). Aspas triplas ''' e """ são equivalentes; """ é a convenção.

python
message = """
Dear Bruno,

Thank you for your order.

Best regards,
The Team
"""

Sequências de escape

Alguns caracteres são difíceis de digitar diretamente dentro de uma string. O Python usa sequências de escape: uma barra invertida seguida por uma letra que representa outra coisa. As duas que você vai usar o tempo todo são \n para uma nova linha e \t para tabulação.

Sequências de escape permitem embutir caracteres que, de outra forma, quebrariam a sintaxe ou não poderiam ser digitados diretamente. As que você vai usar com mais frequência: \n (nova linha), \t (tab), \\ (uma barra invertida literal), \" e \' (aspas dentro de uma string com delimitador igual). Caminhos do Windows exigem barras invertidas, o que colide com o processamento de escape. Prefixe com r para desativá-lo.

O Python suporta o conjunto de escapes no estilo C mais escapes Unicode: \uXXXX (code point de 16 bits), \UXXXXXXXX (32 bits), \xNN (valor hexadecimal de byte), \N{name} (caractere Unicode nomeado). Literais de string raw (r"...") suprimem todo o processamento de escape, passando cada barra invertida diretamente para a string. Isso é essencial para caminhos do Windows e expressões regulares, onde as barras invertidas carregam significado para o consumidor, e não para o tokenizador do Python.

SequênciaCaractere
\nNova linha
\tTab
\\Barra invertida literal
\"Aspas duplas
\'Aspas simples
python
print("Line one\nLine two")        # duas linhas de saída
print("Name:\tBruno")              # Name:   Bruno
path = r"C:\Users\Bruno\Documents" # string raw, sem processamento de escape

Verificando o conteúdo de strings

O Python tem métodos que respondem perguntas de sim/não sobre o que uma string contém. Eles retornam True ou False. O mais útil no início: isdigit() te permite verificar se uma string é só números antes de convertê-la, para que você evite uma falha em caso de entrada inesperada.

Os métodos is* testam, cada um, uma propriedade específica da string inteira e retornam True apenas se cada caractere satisfizer a condição. Seu uso principal é a validação de entrada: verifique antes de converter para evitar uma falha em caso de entrada inesperada. isdigit() antes de int() é o padrão clássico.

Os métodos is* usam verificações de categoria Unicode, não intervalos ASCII. isdigit() retorna True para dígitos sobrescritos e outros code points numéricos Unicode além de 0-9. Para verificação estrita de dígitos ASCII, combine s.isascii() and s.isdigit(). isnumeric() é ainda mais amplo, cobrindo frações e caracteres Unicode com valor numérico. Saiba qual você realmente precisa antes de recorrer a um deles.

python
"42".isdigit()       # True
"hello".isalpha()    # True
"hello42".isalnum()  # True
"   ".isspace()      # True
"Hello".islower()    # False
"HELLO".isupper()    # True

Na prática

Remova os espaços em branco, normalize a caixa, e então extraia o que você precisa. Esta sequência lida com quase qualquer texto fornecido pelo usuário:

python
raw_input = "  [email protected]  "
email     = raw_input.strip().lower()   # "[email protected]"

at_pos   = email.find("@")
username = email[:at_pos]
domain   = email[at_pos + 1:]

print(f"User:   {username}")    # "bruno"
print(f"Domain: {domain}")      # "example.com"

Construindo uma URL a partir de partes e imediatamente validando-a e analisando-a:

python
BASE_URL = "https://api.example.com"
version  = "v2"
resource = "users"
user_id  = 42

url      = f"{BASE_URL}/{version}/{resource}/{user_id}"
# "https://api.example.com/v2/users/42"

protocol = url.split("://")[0]                    # "https"
secured  = url.startswith("https")
domain   = url.split("://")[1].split("/")[0]      # "api.example.com"

print(f"Protocol : {protocol}")
print(f"Secure   : {secured}")
print(f"Domain   : {domain}")

Analisando uma linha de log estruturado usando find(), fatiamento e alinhamento por f-string:

python
log_entry = "[2024-01-15 09:42:11] ERROR: File not found: report.csv"

timestamp = log_entry[1:20]
rest      = log_entry[22:]                # "ERROR: File not found: report.csv"
colon_pos = rest.find(":")
level     = rest[:colon_pos]              # "ERROR"
message   = rest[colon_pos + 2:]          # "File not found: report.csv"

print(f"[{timestamp}] {level:>8}: {message}")
# [2024-01-15 09:42:11]    ERROR: File not found: report.csv

find() localiza o limite, o fatiamento extrai as partes, e a spec de formato >8 alinha à direita o rótulo de severidade para que as colunas permaneçam consistentes quando os nomes dos níveis tiverem comprimentos diferentes.

Referência de métodos

MétodoO que faz
.lower() / .upper()Converte para tudo minúsculo / tudo maiúsculo
.title() / .capitalize()Capitaliza cada palavra / apenas a primeira
.strip() / .lstrip() / .rstrip()Remove espaços em branco circundantes
.find(sub)Índice da primeira ocorrência, ou -1
.count(sub)Quantas vezes sub aparece
.startswith(s) / .endswith(s)Verifica prefixo / sufixo
.replace(old, new)Substitui ocorrências
.split(sep)Divide em uma lista
sep.join(iterable)Junta itens em uma string
.isdigit() / .isalpha() / .isalnum()Verifica o tipo dos caracteres