Recentemente tive a necessidade de atribuir o valor de uma variável numa expressão if em Python, para evitar que um determinado código fosse executado duas vezes.

Expressão If


Supondo que temos o seguinte código.
if a > 0:
    return a

elif foobar(a) > 100:
    return foobar(a)

else:
    return 0


No código acima a expressão foobar(a) é executada 2 vezes, no caso de a variável a não ser superior a 0. A primeira para verificar se o valor da expressão é superior a 100 (foobar(a) > 100) e a segunda para devolver o respectivo valor da expressão (return foobar(a)) caso seja efectivamente superior a 100.




variavel = foobar(a)

if a > 0:
    return a

elif variavel > 100:
    return variavel 

else:
    return 0


Uma das formas de evitar que isso aconteça é atribuir a expressão foobar(a) a uma variável (variavel = foobar(a)) antes do primeiro if. Só que nesse caso a expressão foobar(a) é executada sempre que este código também seja executado, e isso pode ser um problema se o código for executado muitas vezes. Se apenas num pequeno número de casos a expressão foobar(a) for maior que 100, então teremos um enorme gasto de tempo e de processamento absolutamente desnecessários, pois estamos a executar a expressão foobar(a) muitas mais vezes que as necessárias.


Foi assim que decidi procurar uma forma de atribuir o valor a uma variável durante a execução de uma expressão If.

O melhor que encontrei foi a seguinte solução.

class AtribuiValor(object):
    def set(self, valor):
        self.valor = valor
        return valor
    
    def get(self):
        return self.valor
 
def foobar(v):
    return v + 1500

def my_function(a):
    varObj = AtribuiValor()
    
    if a > 0:
        return a
    
    elif varObj.set(foobar(a)) > 100:
        return varObj.get()        
    
    else:
        return 0
    


Neste caso é criada uma instância de um objecto do tipo AtribuiValor e na expressão if atribui-se o valor de foobar(a) ao objecto através da sua função set(), por fim é retornado o valor do objecto chamando a função get() do mesmo. E desta forma a expressão foobar(a) é executada apenas uma vez.


Se alguém conhecer uma solução melhor ou mais pythonica para este "problema", indique-a por favor num comentário a este post.


Actualização

if a > 0:
    return a
else:
    variavel = foobar(a)

    if variavel > 100:
        return variavel
    else:
        return 0

O código acima é uma solução bem mais simples e com o código mais legível, para este problema. Contudo fica a solução para o caso de ser mesmo necessário ou conveniente fazer a atribuição de uma variável numa expressão If.

Obrigado ao Hugo Castilho, Ricardo Castro e Nuno Mariz pelas sugestões.