Antes, umas correções: na primeira função o return value
está dentro do else
. Ou seja, em vez disso:
else:
value == None
return value # return está dentro do else
Deveria ser isso:
else:
value = None
return value # agora está fora do else
Ah, e reparou que vc usou ==
em vez de =
? E fez isso em várias linhas (value == 2
quando deveria ser value = 2
, etc). Enfim, a função correta ficaria assim:
def recieveActionLong(action):
if action == 'create':
value = 1
elif action == 'read':
value = 2
elif action == 'update':
value = 3
elif action == 'delete':
value = 4
else:
value = None
return value
Se bem que também poderia ser assim:
def recieveActionLong(action):
if action == 'create':
return 1
if action == 'read':
return 2
if action == 'update':
return 3
if action == 'delete':
return 4
return None
Afinal, o return
encerra a função e não executa mais nada, então se entrar em um if
, eu garanto que sairá da função e nem precisa do else
.
E na segunda função, behaviors[action] or None
não funciona caso a action
não exista, pois aí dará um KeyError
, pode testar. Para evitar isso, uma opção é trocar pelo método get
, que em vez de lançar exceção, retorna None
caso a chave não exista. Ou seja, ficaria assim:
def recieveActionsShort(action):
behaviors = {
'create': 1,
'read': 2,
'update': 3,
'delete': 4
}
return behaviors.get(action)
Repare também que nem precisa da variável value
, pode retornar direto. Agora vamos à questão em si (sobre qual é "melhor").
Qual é "melhor"?
Eu diria que depende. Como são poucas condições, me parece que tanto faz, o código nem fica tão mais curto assim (na minha opinião). Pelo menos, não tão mais curto que justifique criar um dicionário a cada execução da função. Apesar de ser pequeno, isso tem o seu custo. Vamos fazer um teste rápido com o módulo timeit
:
def recieveActionLong(action):
if action == 'create':
return 1
if action == 'read':
return 2
if action == 'update':
return 3
if action == 'delete':
return 4
return None
def recieveActionsShort(action):
behaviors = {
'create': 1,
'read': 2,
'update': 3,
'delete': 4
}
return behaviors.get(action)
from timeit import timeit
action = 'create'
# executa 1 milhão de vezes cada função
params = { 'number' : 1000000, 'globals': globals() }
# imprime os tempos em segundos
print(timeit('recieveActionLong(action)', **params))
print(timeit('recieveActionsShort(action)', **params))
Os tempos são impressos em segundos e claro que varia conforme o hardware. Na minha máquina o resultado foi:
0.058050006002304144
0.13243731600232422
Ou seja, a versão mais curta é cerca de 2,2 vezes mais lenta.
É claro que se a função for executada poucas vezes, isso será imperceptível e desprezível. Mas é só pra dizer que a suposta "facilidade" não vem de graça, criar um dicionário a cada execução tem o seu custo e cabe a vc avaliar se faz ou não diferença no seu caso.
Uma vantagem que eu vejo na segunda abordagem é se o dicionário fosse um parâmetro da função:
def recieveActionsShort(action, behaviors):
return behaviors.get(action)
action = 'read'
result = recieveActionsShort(action, { 'create': 1, 'read': 2, 'update': 3, 'delete': 4 })
print(result) # 2
# usando um grupo diferente de opções
result = recieveActionsShort(action, { 'read': 99, 'write': 88, 'append': 77 })
print(result) # 99
Dessa forma fica mais dinâmico e eu vejo uma justificativa maior para usar um dicionário. Se for um conjunto de opções fixas, não vejo tanto ganho assim. Se a quantidade de opções é muito grande, talvez valha a pena criar o dicionário apenas uma vez fora da função, por exemplo.
Mas aí o "melhor" depende muito do contexto. Código menor não é necessariamente melhor, muitas vezes a tentativa de escrever menos linhas pode deixá-lo confuso.