I would do different. Instead of just testing if it is a number, the function could already ask you to type again, and return the value only if it is valid. The solution of another answer, although it works, it converts the string to number twice (inside the function is called float
only to check if it is number, and then out of function it is called again to be able to make comparisons). Not to mention that each message is printed twice, which makes it difficult to maintain (if you want to change the message, you have to change in more than one place).
Anyway, the function could be like this:
def ler_valor(mensagem, mensagem_erro):
while True:
try:
valor = float(input(mensagem))
if valor < 0:
print(mensagem_erro)
else:
return valor
except ValueError:
print(mensagem_erro)
saldo = ler_valor('Please enter Saldo: ', 'Please enter a valid value: ')
while True
creates a loop infinity. That is, as long as the entered value is not valid, I keep asking you to type again. I included a check for when the number is negative, as I understood from the rest of the code, the value can only be positive.
If the value is valid, I return (the return
exits the function, and consequently interrupts the loop infinite).
That is, if the function returned something, it is because for sure the value is valid, and I do not need to test again. Note that in the other answer the if
is redundant, because the code only comes out of the while
when the balance is a number, then you left the loop is because it’s a number, and so I wouldn’t need to test it again.
Now these if
's:
if saldo >= 0 and saldo <= 200:
credito = 0
if saldo >= 201 and saldo <= 400:
credito = 0.2 * saldo
...
If the balance is 100, he enters the first if
. But soon after he will test the second if
, only that this is unnecessary, because if he has already entered the first, he certainly will not enter the second, since the conditions are conflicting (there is no way to be less than 200 and greater than 201 at the same time). The same goes for others if
's: the way it is, you will test all conditions unnecessarily.
Not to mention that the last condition is wrong. If the value is 601, it will not enter any of the if
's.
Instead of that, use else
and elif
:
if saldo <= 200:
credito = 0
elif saldo <= 400:
credito = 0.2 * saldo
elif saldo <= 600:
credito = 0.3 * saldo
else:
credito = 0.4 * saldo
As the function has already ensured that the value is not negative, I no longer need to test if the value is greater than zero.
In addition the conditions have been simplified. If the value is less than or equal to 200, it enters the first if
and does not test the other conditions.
If you don’t get into the first one if
, is because the value is greater than 200, so I I don’t need to test it again in the elif
. If you arrived at the first elif
is because there at that point the value is definitely greater than 200, so I just need to test whether it is less than or equal to 400.
If you didn’t enter the first elif
, then surely the value is greater than 400 and I do not need to test it again in the second elif
(I just need to test if it’s <= 600).
Finally, at the last else
: if it got there is because for sure the value is greater than 600 so I don’t need to test any more conditions.
In addition to avoiding unnecessary testing, this code also makes maintenance easier, because if the value ranges change, you only need to change them once (if you repeat the conditions, you will have to change them twice).
Thank you very much! I managed to solve the question.
– Giovanne Lucas
@Giovannelucas O
if isNumber
is unnecessary in this case. If the code has left thewhile
it is becauseisNumber
returnedTrue
, then there is no need to test it again. There are other details that you can hit too, see my answer :-)– hkotsubo