XOR lógico

Quem conhece operadores lógicos? São um bloco fundamental da programação e uma das coisas mais usadas no dia a dia. Os operadores lógicos no Python são o and, or e not. Conhece?

Os manjadores de escovação de bit conhecerão outro operador que por vezes é usado em lógica binária: o xor, ou "ou exclusivo" (eXclusive OR). Como o nome indica, o xor é um operador que aceita uma entrada e uma saída, e retorna True se uma, e somente uma das entradas, for True.

Em melhor estilo "de volta à faculdade", segue a tabela verdade:

Entrada 1Entrada 2Saída
FalseFalseFalse
FalseTrueTrue
TrueFalseTrue
TrueTrueFalse

Um caso de uso recente que me inspirou a escrever esse post foi escrever uma função que aceitava parâmetros de dois jeitos: um argumento fixo e requerido, e a opção entre passar um de outros dois argumentos; simplificando um pouco, algo assim:

def minha_funcao(num_1, num_somar=None, num_subtrair=None):
    if num_somar:
        return num_1 + num_somar
    else:
        return num_1 - num_subtrair

Claro que a função nesse caso ainda funciona se os dois parâmetros num_somar e num_subtrair forem passados (dando prioridade pra soma), mas é prudente emitir um erro se tentarmos usar a função de modo errado pra deixar claro o funcionamento do negócio.

Assim, se quisermos verificar se um argumento ou o outro foi passado, mas não os dois, e não nenhum dos dois, temos que fazer uma coisa verbosa mais ou menos assim:

def minha_funcao(num_1, num_somar=None, num_subtrair=None):
    
    # Se ambos ou nenhum dos dois estiver definido...
    if (num_somar is not None and num_subtrair is not None) or (num_somar is None and num_subtrair is None):
        raise ValueError('Um, e somente um dos parâmetros `num_somar` e `num_subtrair` deve ser informado!')
    
    if num_somar:
        return num_1 + num_somar
    else:
        return num_1 - num_subtrair

Feio, né?

Com o xor (símbolo: ^) podemos simplificar bastante a expressão:

def minha_funcao(num_1, num_somar=None, num_subtrair=None):
    # Se ambos ou nenhum dos dois estiver definido...
    if not ((num_somar is None) ^ (num_subtrair is None)):
        raise ValueError('Um, e somente um dos parâmetros `num_somar` e `num_subtrair` deve ser informado!')

    if num_somar:
        return num_1 + num_somar
    else:
        return num_1 - num_subtrair
Show Comments

Get the latest posts delivered right to your inbox.