Atualizado: 04/11/2024

Tuplas no Pattern Matching - Python

Em Python, tuplas podem ser usadas como padrões no pattern matching. Por exemplo:

def print_data(user):
    match user:
        case ("Tom", 37):
            print("default user")
        case ("Tom", age):
            print(f"Age: {age}")
        case (name, 22):
            print(f"Name: {name}")
        case (name, age):
            print(f"Name: {name}  Age: {age}")
 
 
print_data(("Tom", 37))     # default user
print_data(("Tom", 28))     # Age: 28
print_data(("Sam", 22))     # Name: Sam
print_data(("Bob", 41))     # Name: Bob  Age: 41
print_data(("Tom", 33, "Google"))    # não corresponde a nenhum dos padrões

Nesse caso, a função recebe o parâmetro user, que representa uma tupla de dois elementos. A estrutura match compara essa tupla com uma série de padrões. O primeiro padrão exige que a tupla user corresponda exatamente aos valores:

case ("Tom", 37):
    print("default user")

Ou seja, se o primeiro elemento da tupla for "Tom" e o segundo for 37, a mensagem "default user" será impressa no console.

O segundo padrão corresponde a qualquer tupla de dois elementos cujo primeiro elemento seja a string "Tom":

case ("Tom", age):
    print(f"Age: {age}")

Aqui, o segundo elemento é atribuído à variável age. Portanto, se o primeiro elemento da tupla for "Tom" e o segundo não for 37, a tupla corresponderá ao segundo padrão, e o valor do segundo elemento será armazenado em age.

O terceiro padrão é semelhante, mas agora o segundo elemento da tupla deve ser exatamente 22, e o primeiro elemento é atribuído à variável name:

case (name, 22):
    print(f"Name: {name}")

Se a tupla de dois elementos não corresponder aos três primeiros padrões, ela corresponderá ao quarto padrão, no qual não nos importamos com os valores específicos: eles são atribuídos às variáveis name e age:

case (name, age):
    print(f"Name: {name}  Age: {age}")

Valores Alternativos

Se for necessário que um elemento da tupla corresponda a um conjunto de valores, esses valores podem ser listados usando o operador | (barra vertical):

def print_data(user):
    match user:
        case ("Tom" | "Tomas" | "Tommy", 37):
            print("default user")
        case ("Tom", age):
            print(f"Age: {age}")
        case (name, 22):
            print(f"Name: {name}")
        case (name, age):
            print(f"Name: {name}  Age: {age}")
 
 
print_data(("Tom", 37))     # default user
print_data(("Tomas", 37))   # default user
print_data(("Tom", 28))     # Age: 28
print_data(("Sam", 37))     # Name: Sam  Age: 37

Nesse caso, o primeiro padrão corresponde a uma tupla de dois elementos onde o primeiro elemento é "Tom", "Tomas" ou "Tommy".

Também é possível definir valores alternativos para tuplas inteiras:

def print_data(user):
    match user:
        case ("Tom", 37) | ("Sam", 22):
            print("default user")
        case (name, age):
            print(f"Name: {name}  Age: {age}")
    
    
print_data(("Tom", 37))     # default user
print_data(("Sam", 22))     # default user
print_data(("Mike", 28))    # Name: Mike  Age: 28

Aqui, o primeiro padrão corresponderá a duas tuplas específicas: ("Tom", 37) e ("Sam", 22).

Omissão de Elementos

Se não nos importamos com um elemento específico da tupla, podemos usar o caractere _ no padrão:

def print_data(user):
    match user:
        case ("Tom", 37):
            print("default user")
        case (name, _):     # o segundo elemento não é importante
            print(f"Name: {name}")
 
 
print_data(("Tom", 37))     # default user
print_data(("Sam", 25))     # Name: Sam
print_data(("Bob", 41))     # Name: Bob

Podemos usar o sublinhado para todos os elementos da tupla; nesse caso, os valores desses elementos não são importantes:

def print_data(user):
    match user:
        case ("Tom", 37):
            print("default user")
        case ("Sam", _):
            print("Name: Sam")
        case (_, _):
            print("Undefined user")
 
 
print_data(("Tom", 37))     # default user
print_data(("Sam", 25))     # Name: Sam
print_data(([1, 2, 3], 41))     # Undefined user

Note que, no último caso, o padrão (_, _) ainda corresponde apenas a tuplas de dois elementos.

No exemplo anterior, os padrões aplicados correspondiam apenas a tuplas de dois elementos. No entanto, também é possível usar padrões de tuplas com diferentes números de elementos:

def print_data(user):
    match user:
        case (name, age):
            print(f"Name: {name}  Age: {age}")
        case (name, age, company):
            print(f"Name: {name}  Age: {age}  Company: {company}")
        case (name, age, company, lang):
            print(f"Name: {name}  Age: {age}  Company: {company}  Language: {lang}")
 
 
print_data(("Tom", 37))                     # Name: Tom  Age: 37
print_data(("Sam", 22, "Microsoft"))        # Name: Sam  Age: 22  Company: Microsoft
print_data(("Bob", 41, "Google", "English"))  # Name: Bob  Age: 41  Company: Google  Language: English

Tupla com Número Indefinido de Elementos

Se for necessário comparar uma expressão com uma tupla de comprimento indefinido, podemos usar o símbolo * para capturar os elementos restantes:

def print_data(user):
    match user:
        case ("Tom", 37, *rest):
            print(f"Rest: {rest}")
        case (name, age, *rest):
            print(f"{name} ({age}): {rest}")
 
 
print_data(("Tom", 37))               # Rest: []
print_data(("Tom", 37, "Google"))     # Rest: ['Google']
print_data(("Bob", 41, "Microsoft", "English"))  # Bob (41): ['Microsoft', 'English']

No exemplo acima, o parâmetro *rest captura todos os elementos adicionais. Os padrões ("Tom", 37, *rest) e (name, age, *rest) correspondem a qualquer tupla com dois ou mais elementos. Todos os elementos a partir do terceiro são armazenados na lista rest.

Se não nos importamos com os elementos restantes, mas ainda queremos corresponder a tuplas com um número indefinido de elementos, podemos usar *_:

def print_data(user):
    match user:
        case ("Tom", 37, *_):
            print("Default user")
        case (name, age, *_):
            print(f"{name} ({age})")
 
 
print_data(("Tom", 37))               # Default user
print_data(("Tom", 37, "Google"))     # Default user
print_data(("Bob", 41, "Microsoft", "English"))  # Bob (41)

Nesse caso, *_ indica que não estamos interessados nos elementos adicionais, mas o padrão ainda corresponderá a tuplas com dois ou mais elementos.

Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com