Executando verificação de segurança...
3

Muito bom! Complementando, todas estas opções de formatação podem ser encontradas na documentação (é bem ampla, com várias outras opções, sugiro a leitura).

Um detalhe interessante é que os parâmetros de formatação (tamanho, alinhamento, etc) podem ser dinâmicos:

def fstring(texto, fill_char, align, size):
    print(f'{texto:{fill_char}{align}{size}}')

fstring('olá', '+', '<', 10) # olá+++++++
fstring('olá', '.', '^', 15) # ......olá......

E não se resume a variáveis, eu posso colocar qualquer expressão, desde que resulte em um caractere válido:

# escolhe as opções aleatoriamente
from random import choice
aligns = ['<', '>', '^']
fill_chars = ['-', '.', '+', '_', '*']
sizes = [10, 15, 20]

# cada vez que rodar, vai escolher opções diferentes
print(f'{"olá":{choice(fill_chars)}{choice(aligns)}{choice(sizes)}}')

Repare também que a string a ser formatada não precisa estar em uma variável, eu posso colocá-la diretamente ali. A única exigência é que se use aspas diferentes da f-string.

Vale lembrar também que é possível ter f-strings aninhadas:

print(f'{", ".join(f"{n:03}" for n in range(10)):_>60}')
# ____________000, 001, 002, 003, 004, 005, 006, 007, 008, 009

O importante é que a f-string interna use aspas diferentes da externa.