Skip to content

    Chapter 11, Basic

    Strings

    A string is an immutable sequence of Unicode characters. The most important word in this sentence is "immutable".

    Code for this chapter: basico/cap11_strings.py

    Indices and slices

    Each character has a position, starting at zero. Negative indices count from the end. The slice [início:fim:passo] excludes the final index:

    basico/cap11_strings.pylinhas 10 a 11
    texto = "Python"
    print(texto[0], texto[-1], texto[1:4], texto[::-1])
    
    Output
    P n yth nohtyP
    

    Strings are immutable

    No operation alters an existing string. They always create a new one:

    basico/cap11_strings.pylinhas 16 a 22
    try:
        texto[0] = "J"
    except TypeError as erro:
        print(erro)
    
    novo = "J" + texto[1:]
    print(novo)
    
    Output
    'str' object does not support item assignment
    Jython
    

    Everyday methods

    These are the methods I use every week. All return a new string (or another value) and leave the original intact:

    basico/cap11_strings.pylinhas 27 a 37
    frase = "  Aprender Python é divertido  "
    print(frase.strip())
    print(frase.strip().lower())
    print(frase.strip().upper())
    print(frase.strip().split())
    print("-".join(["a", "b", "c"]))
    print(frase.replace("Python", "Go").strip())
    print(frase.find("Python"))
    print(frase.strip().startswith("Aprender"))
    print(frase.count("e"))
    print("Python" in frase)
    
    Output
    Aprender Python é divertido
    aprender python é divertido
    APRENDER PYTHON É DIVERTIDO
    ['Aprender', 'Python', 'é', 'divertido']
    a-b-c
    Aprender Go é divertido
    11
    True
    3
    True
    

    The find returns -1 when not found. The index does the same, but raises ValueError. To decide if one string contains another, use the operator in.

    f-strings

    F-strings are the modern way to format text. After the colon goes the format of the value:

    basico/cap11_strings.pylinhas 42 a 49
    nome = "Ana"
    preco = 1234.5
    quantidade = 3
    print(f"{nome} comprou {quantidade} itens")
    print(f"Preço: {preco:,.2f}")
    print(f"Total: {preco * quantidade:.2f}")
    print(f"[{nome:>8}] [{nome:<8}] [{nome:^8}]")
    print(f"{quantidade=}")
    
    Output
    Ana comprou 3 itens
    Preço: 1,234.50
    Total: 3703.50
    [     Ana] [Ana     ] [  Ana   ]
    quantidade=3
    

    The format :,.2f uses a comma for thousands and a period for decimals, which is the American standard. For the Brazilian format, swap the symbols:

    basico/cap11_strings.pylinhas 51 a 54
    preco = 1234.5
    americano = f"{preco:,.2f}"
    brasileiro = americano.replace(",", "_").replace(".", ",").replace("_", ".")
    print(brasileiro)
    
    Output
    1.234,50
    

    For real applications, the module locale or the Babel library does this by region. For a script, the above swap solves it.

    Unicode and bytes

    A string is a sequence of code points Unicode. Bytes only come into play when you write to disk or send over the network, and then the encoding matters:

    basico/cap11_strings.pylinhas 59 a 65
    print(ord("A"), chr(97))
    palavra = "ação"
    print(len(palavra))
    dados = palavra.encode("utf-8")
    print(dados)
    print(len(dados))
    print(dados.decode("utf-8"))
    
    Output
    65 a
    4
    b'a\xc3\xa7\xc3\xa3o'
    6
    ação
    

    The word ação has 4 characters and occupies 6 bytes in UTF-8, because ç and ã use two bytes each. Always state the encoding explicitly when reading and writing files. I will revisit this in the file chapter.

    Exercise 1

    Palindrome

    Write eh_palindromo(texto) that ignores uppercase letters and spaces. Tip: lower, replace and a reversed slice solve it without a loop.

    Exercise 2

    Reversing the order of words

    Write inverter_palavras("python é bom") that returns "bom é python".