Strings do Python

O Python tem uma classe de string integrada chamada "str" com muitos recursos úteis (há um módulo mais antigo chamado "string", que não deve ser usado). Os literais de string podem ser delimitados por aspas duplas ou simples, embora as aspas simples sejam as mais usadas. Os escapes de barra invertida funcionam normalmente em literais entre aspas simples e duplas, por exemplo, \n \' \". Um literal de string entre aspas duplas pode conter aspas simples sem complicações (por exemplo, "Eu não fiz isso"). Da mesma forma, strings entre aspas simples podem conter aspas duplas. Um literal de string pode abranger várias linhas, mas deve haver uma barra invertida \ no final de cada linha para escapar a nova linha. Os literais de strings dentro de aspas triplas, """ ou ''', podem abranger várias linhas de texto.

As strings Python são "imutáveis", ou seja, não podem ser alteradas depois de criadas (as strings Java também usam esse estilo imutável). Como as strings não podem ser alteradas, construímos strings *novas* para representar valores computados. Por exemplo, a expressão ("hello" + "there") aceita as duas strings "hello" e "there" e cria uma nova string "hellothere".

Os caracteres em uma string podem ser acessados usando a sintaxe padrão [ ] e, como Java e C++, Python usa indexação baseada em zero, portanto, se s é 'hello' s[1] é 'e'. Se o índice estiver fora dos limites para a string, o Python vai gerar um erro. O estilo Python (ao contrário do Perl) é para se parar se ele não consegue dizer o que fazer, em vez de apenas criar um valor padrão. A útil sintaxe de "fatia" (abaixo) também funciona para extrair qualquer substring de uma string. A função len(string) retorna o tamanho de uma string. A sintaxe [ ] e a função len() funcionam com qualquer tipo de sequência: strings, listas etc. O Python tenta fazer as operações funcionarem de forma consistente em tipos diferentes. Quem está começando em Python pegou: não use "len" como nome de variável para evitar o bloqueio da função len(). O operador "+" pode concatenar duas strings. Observe no código abaixo que as variáveis não são pré-declaradas; basta atribuir a elas e começar.

  s = 'hi'
  print(s[1])          ## i
  print(len(s))        ## 2
  print(s + ' there')  ## hi there

Ao contrário do Java, o "+" não converte automaticamente números ou outros tipos em formato de string. A função str() converte valores em uma forma de string para que eles possam ser combinados com outras strings.

  pi = 3.14
  ##text = 'The value of pi is ' + pi      ## NO, does not work
  text = 'The value of pi is '  + str(pi)  ## yes

Para números, os operadores padrão +, /, * funcionam da maneira habitual. Não há operador ++, mas +=, -= etc. funcionam. Se você quiser uma divisão de números inteiros, use duas barras (por exemplo, 6 // 5 é 1)

A função "print" normalmente imprime um ou mais itens Python seguidos por uma nova linha. Um literal de string "bruta" é prefixado por um "r" e passa todos os caracteres sem tratamento especial de barras invertidas, então r'x\nx' é avaliado como a string de comprimento 4 'x\nx'. "print" pode usar vários argumentos para mudar a forma como mostra as informações (consulte Definição da função de impressão python.org). Por exemplo, definir "end" como "" para não mostrar mais uma nova linha depois que terminar de mostrar todos os itens.

  raw = r'this\t\n and that'

  # this\t\n and that
  print(raw)

  multi = """It was the best of times.
  It was the worst of times."""

  # It was the best of times.
  #   It was the worst of times.
  print(multi)

Métodos de string

Aqui estão alguns dos métodos de string mais comuns. Um método é como uma função, mas é executado "em" um objeto. Se a variável s for uma string, o código s.lower() executará o método lower() nesse objeto de string e retornará o resultado (essa ideia de um método executado em um objeto é uma das ideias básicas que compõem a Programação Orientada a Objetos, OOP). Confira alguns dos métodos de string mais comuns:

  • s.lower(), s.upper() -- retorna a versão em letras minúsculas ou maiúsculas da string
  • s.strip(): retorna uma string com espaço em branco removido do início e do fim.
  • s.isalpha()/s.isdigit()/s.isspace()... -- testa se todos os caracteres da string estão nas várias classes de caracteres
  • s.startswith('other'), s.endswith('other') -- testa se a string começa ou termina com a outra string especificada
  • s.find('other') -- procura a outra string especificada (não uma expressão regular) em s e retorna o primeiro índice onde ela começa ou -1 se não for encontrado
  • s.replace('old', 'new') -- retorna uma string em que todas as ocorrências de "old" foram substituídas por "new"
  • s.split('delim') -- retorna uma lista de substrings separadas pelo delimitador fornecido. O delimitador não é uma expressão regular, é apenas texto. 'aaa,bbb,resourcemanager'.split(',') -> ['aaa', 'bbb', 'ccc']. Como um caso especial conveniente, s.split() (sem argumentos) divide todos os caracteres do espaço em branco.
  • s.join(list) -- o oposto de split(), junta os elementos da lista em questão usando a string como delimitador. Por exemplo, '---'.join(['aaa', 'bbb', 'gp']) -> aaa---bbb---resourcemanager

Uma pesquisa no Google por "python str" deve levar você aos métodos de string python.org oficiais, que listam todos os métodos str.

O Python não tem um tipo de caractere separado. Em vez disso, uma expressão como s[8] retorna uma string-length-1 contendo o caractere. Com essa string-length-1, os operadores ==, <=, ... funcionam como o esperado, então, na maioria das vezes, você não precisa saber que o Python não tem um tipo "char" escalar separado.

Fatias de strings

A sintaxe "fatia" é uma forma prática de se referir a subpartes de sequências, normalmente strings e listas. A fatia s[start:end] é o elemento que começa no início e se estende até o final, mas sem incluí-lo. Suponha que temos s = "Hello"

a string &quot;hello&quot; com índices de letras 0 1 2 3 4

  • s[1:4] é 'ell' -- caracteres começando no índice 1 e se estendendo até, mas não incluindo, o índice 4
  • s[1:] é "ello", ou seja, a omissão de qualquer índice assume como padrão o início ou o fim da string
  • s[:] é "Olá". A omissão de ambos sempre nos dá uma cópia da coisa inteira (essa é a maneira pythonic de copiar uma sequência como uma string ou lista)
  • s[1:100] é "ello" -- um índice muito grande é truncado no comprimento da string

Os números de índice padrão baseados em zero dão acesso fácil a caracteres próximos ao início da string. Como alternativa, o Python usa números negativos para facilitar o acesso aos caracteres no final da string: s[-1] é o último caractere "o", s[-2] é "l" o último caractere e assim por diante. Números de índice negativo são contados a partir do final da string:

  • s[-1] é 'o' -- último caractere (1o depois do fim)
  • s[-4] é 'e' -- 4o do fim
  • s[:-3] é 'Ele', vai até os últimos 3 caracteres, mas sem incluir.
  • s[-3:] é 'llo', começando pelo terceiro caractere do final e se estendendo até o fim da string.

É um truque real de frações que, para qualquer índice n, é s[:n] + s[n:] == s. Isso funciona mesmo para n negativos ou fora dos limites. Ou, em outras palavras, s[:n] e s[n:] sempre particionam a string em duas partes, preservando todos os caracteres. Como veremos na seção da lista mais adiante, as fatias também funcionam com listas.

Formatação de strings

Uma coisa interessante que o Python pode fazer é converter objetos automaticamente em uma string adequada para impressão. Duas maneiras integradas de fazer isso são literais de string formatados, também chamados de "f-strings", e a invocação de str.format().

Literais de strings formatados

Muitas vezes, os literais de string formatados são usados em situações como:

  value = 2.791514
  print(f'approximate value = {value:.2f}')  # approximate value = 2.79

  car = {'tires':4, 'doors':2}
  print(f'car = {car}') # car = {'tires': 4, 'doors': 2}

Uma string literal formatada é prefixada com "f" (como o prefixo "r" usado para strings brutas). Todo texto fora das chaves '{}' é mostrado diretamente. As expressões contidas em "{}" são impressas usando a especificação de formato descrita na especificação de formato.Há muitas coisas interessantes que podem ser feitas com a formatação, incluindo truncamento e conversão para notação científica e alinhamento à esquerda/direita/central.

f-strings são muito úteis quando você quer imprimir uma tabela de objetos e quer que as colunas que representam diferentes atributos de objetos fiquem alinhadas da seguinte forma

  address_book = [{'name':'N.X.', 'addr':'15 Jones St', 'bonus': 70},
      {'name':'J.P.', 'addr':'1005 5th St', 'bonus': 400},
      {'name':'A.A.', 'addr':'200001 Bdwy', 'bonus': 5},]

  for person in address_book:
    print(f'{person["name"]:8} || {person["addr"]:20} || {person["bonus"]:>5}')

  # N.X.     || 15 Jones St          ||    70
  # J.P.     || 1005 5th St          ||   400
  # A.A.     || 200001 Bdwy          ||     5

String %

O Python também possui um recurso mais antigo do tipo printf() para montar uma string. O operador % usa uma string de formato printf-type à esquerda (%d int, string %s, ponto flutuante %f/%g) e os valores correspondentes em uma tupla à direita (uma tupla é composta de valores separados por vírgulas, normalmente agrupados entre parênteses):

  # % operator
  text = "%d little pigs come out, or I'll %s, and I'll %s, and I'll blow your %s down." % (3, 'huff', 'puff', 'house')

A linha acima é meio longa -- suponha que você deseja quebrá-la em linhas separadas. Você não pode simplesmente dividir a linha após "%", como faria em outras linguagens, já que, por padrão, o Python trata cada linha como uma instrução separada (no lado do sinal de adição, é por isso que não precisamos digitar ponto e vírgula em cada linha). Para corrigir isso, coloque a expressão inteira entre parênteses externos. Assim, a expressão poderá abranger várias linhas. Essa técnica de código em todas as linhas funciona com as várias construções de agrupamento detalhadas abaixo: ( ), [ ], { }.

  # Add parentheses to make the long line work:
  text = (
    "%d little pigs come out, or I'll %s, and I'll %s, and I'll blow your %s down."
    % (3, 'huff', 'puff', 'house'))

Isso é melhor, mas a fila ainda está um pouco longa. O Python permite recortar uma linha em pedaços, que serão concatenados automaticamente. Então, para tornar essa linha ainda mais curta, podemos fazer isto:

  # Split the line into chunks, which are concatenated automatically by Python
  text = (
    "%d little pigs come out, "
    "or I'll %s, and I'll %s, "
    "and I'll blow your %s down."
    % (3, 'huff', 'puff', 'house'))

Strings (Unicode x bytes)

As strings do Python regulares são Unicode.

O Python também é compatível com strings compostas por bytes simples, indicados pelo prefixo "b" na frente de um literal de string, como:

> byte_string = b'A byte string'
> byte_string
  b'A byte string'

Uma string Unicode é um tipo diferente de objeto de uma string de bytes, mas várias bibliotecas, como expressões regulares, funcionam corretamente se um tipo de string é transmitido.

Para converter uma string Python normal em bytes, chame o método encode() na string. Na outra direção, o método decode() da string de byte converte bytes simples codificados em uma string unicode:

> ustring = 'A unicode \u018e string \xf1'
> b = ustring.encode('utf-8')
> b
b'A unicode \xc6\x8e string \xc3\xb1'  ## bytes of utf-8 encoding. Note the b-prefix.
> t = b.decode('utf-8')                ## Convert bytes back to a unicode string
> t == ustring                         ## It's the same as the original, yay!

True

Na seção de leitura de arquivos, há um exemplo que mostra como abrir um arquivo de texto com alguma codificação e ler strings Unicode.

Instrução If

O Python não usa { } para incluir blocos de código para if/loops/função etc. Em vez disso, o Python usa dois-pontos (:) e recuo/espaço em branco para agrupar instruções. O teste booleano para um if não precisa estar entre parênteses (grande diferença de C++/Java) e pode ter as cláusulas *elif* e *else* (mnemônico: a palavra "elif" tem o mesmo tamanho que a palavra "else").

Qualquer valor pode ser usado como um teste "if". Todos os valores "zero" contam como falsos: nenhum, 0, string vazia, lista vazia, dicionário vazio. Há também um tipo booleano com dois valores: True e False (convertidos em um int; são 1 e 0). O Python tem as operações de comparação usuais: ==, !=, <, <=, >, >=. Ao contrário de Java e C, == é sobrecarregado para funcionar corretamente com strings. Os operadores booleanos são as palavras escritas *e*, *ou*, *não* (o Python não usa o estilo C && || !). Veja como seria o código para um aplicativo de saúde que fornece recomendações de bebida ao longo do dia. Observe como cada bloco das declarações "then/else" começa com um : e as declarações são agrupadas pelo recuo:

  if time_hour >= 0 and time_hour <= 24:
    print('Suggesting a drink option...')
    if mood == 'sleepy' and time_hour < 10:
      print('coffee')
    elif mood == 'thirsty' or time_hour < 2:
      print('lemonade')
    else:
      print('water')

Acho que omitir o ":" é meu erro de sintaxe mais comum ao digitar o tipo de código acima, provavelmente porque isso é algo adicional para digitar em comparação com meus hábitos C++/Java. Além disso, não coloque o teste booleano entre parênteses. Isso é um hábito de C/Java. Se o código for curto, você poderá colocá-lo na mesma linha depois de ":", desta forma (isso se aplica a funções, loops, etc.), embora algumas pessoas considerem mais legível espaçar elementos em linhas separadas.

  if time_hour < 10: print('coffee')
  else: print('water')

Exercício: string1.py

Para praticar o material desta seção, faça o exercício string1.py dos Exercícios básicos.