String validation using while in Python

Asked

Viewed 94 times

-2

The following code is intended to ask for the user’s gender ("f" or "m") and if the user typed another letter, he would continue to ask to type "f" or "m", however when executing it he keeps asking for sex, same user typing "f" or "m".

sexo = 'o'

while (sexo != 'f' or sexo != 'm'):
    sexo = input('Digite seu sexo (m / f): ')

The same thing happens when I request the user’s marital status :

estado_civil = 'a'
while estado_civil != 's' or estado_civil != 'c' or estado_civil != 'v' or estado_civil != 'd':
    estado_civil = input('Digite seu estado civil (s, c, v, d): ')

I was able to solve the problem using the following code, but I would like to know the reason why it does not work using the above code:

while True:
  sexo = input('Digite seu sexo (m / f): ')
  if sexo == 'f' or sexo == 'm':
    break

while True:
  estado_civil = input('Digite seu estado civil (s, c, v, d): ')
  if estado_civil == 's' or estado_civil == 'c' or estado_civil == 'v' or estado_civil == 'd':
    break
  • 1

    Change of while (sexo != 'f' or sexo != 'm'): for while (sexo != 'f' and sexo != 'm'):

3 answers

2


The reason one code worked, but the other one didn’t, is very simple.

In the while, the condition serves to indicate whether it will continue performing or not. As long as the condition is true, it continues.

So you did:

while (sexo != 'f' or sexo != 'm'):
    sexo = input('Digite seu sexo (m / f): ')

The condition of while is sexo != 'f' or sexo != 'm', which are actually two conditions plus the operator or. In the end, this whole expression checks whether sexo is different from "f" or is different from "m". The result of or is true (True) if either of the two conditions is true (only one of them already serves). That is, if sexo is different from "f", the result is True. But if it’s different from "m," it’s also True.

So what happens if you type "f"? It won’t be different from "f", but it will be different from "m". Like the or just needs one of the conditions to be true, the result is True, and therefore the while continues to perform.

What if you type "m"? It will be different from "f", which is already enough for the result of or be it True, and therefore the while continues to perform.

In fact, this condition will always be true: any value other than "f" will fall into the first condition and the result will be True. And if you type "f", the first condition is false, but the second ("f" is different from "m") is true, also resulting in True. So you created a loop infinite.

Valor sexo != 'f' sexo != 'm' sexo != 'f' or sexo != 'm'
"f" False True True
"m" True False* True
is not "f" or "m" True True* True

I mean, the condition will always be True, regardless of the value of sexo. That’s why the while continues running, regardless of what is typed.

* In fact, if the first expression is True, the second is not even assessed, since operators boolean sane Circuit short (only assess the minimum necessary: as in or just that one of them is True, if the first is, the second is not evaluated).


So what you want is that the loop continue running only if the sexo not "f" or "m" (that is, if you type something that is not "f" and also is not "m", I continue, but if it is one of the two, I stop). Therefore the correct operator to be used is the and:

sexo = ''
while sexo != 'f' and sexo != 'm': # repare que não precisa dos parênteses
    sexo = input('Digite seu sexo (m / f): ')

The and only results in True if both conditions are true. That is, if I type "f", the first condition is false (no different than "f") and the result will be False. And if you type "m", the first condition is true (it’s different from "f"), but the second one is false (it’s no different than "m"), and the result will also be False. So if I type "f" or "m," it comes out of the while. For any other value, the loop continues.

See the difference:

Valor sexo != 'f' sexo != 'm' sexo != 'f' and sexo != 'm'
"f" False True False
"m" True False False
is not "f" or "m" True True True

I mean, now the condition is only true if I don’t type "f" or "m," and then the while continues. If I type any of them, the result is False and the while is interrupted.


I particularly don’t like this solution of giving an arbitrary value to the variable before the loop, just so he can get in there once. I’d rather do as his second code:

while True:
  sexo = input('Digite seu sexo (m / f): ')
  if sexo == 'f' or sexo == 'm':
    break

It works because instead of != (different), you used == (equal), so now the condition checks whether it was typed "f" or "m" (if sexo is equal to "f" or equal to "m"). If I type "f" or "m", it enters the if and the break interrupts the while. For any other value, it does not enter the if and the loop continues.

So now it’s like this:

Valor sexo == 'f' sexo == 'm' sexo == 'f' or sexo == 'm'
"f" True False True
"m" False True True
is not "f" or "m" False False False

That is, if you type "f" or "m", you enter if and interrupts the loop. If you type anything other than "f" or "m," you don’t enter if and the while continues to perform.

That’s why the second code worked, but the first one didn’t.


Of course, you can implement in other ways, as the other answers suggest (if sexo in ('m', 'f'), etc), but there is no longer the focus of the question. The important thing is to understand how conditionals work and apply them correctly.

In short:

  • an expression with or results in True if any one of the conditions is true
  • an expression with and results in True if all the conditions are true
  • 1

    A lesson, thank you! :)

0

If you are using python 3.8 or higher, may implement Assigment Expression (Assignment expression) in your code to perform the checks. This way the code would look:

while (s := input('Sexo: [M/F] ').upper()) not in {'M', 'F'}:
    print('Sexo INVÁALIDO!')

while (e := input('Estado Civil: [S/C/V/D] ').upper()) not in {'S', 'C', 'V', 'D'}:
    print('Estado Civil INVÁLIDO!')

How the code works?

The first block while checks whether the value assigned to the variable s belongs or does not belong to the set...

{'M', 'F'}

While not belonging, the error message will be displayed and, also, the sex will be requested again. Otherwise, the loop will close and move to the next code block.

The second while block has functioning analogous to the first. Only this time the check will have four possibilities that are:

{'S', 'C', 'V', 'D'}

-3

Hello, we can solve this problem by avoiding the use of break.

sexo = ''
while sexo not in ['f','m']:
  sexo = input('Digite seu sexo (m / f): ')
  sexo = sexo.lower()
  
estadoCivil = ''
while estadoCivil not in ['s','c','v','d']:
  estadoCivil = input('Digite seu estado civil (s, c, v, d): ')
  estadoCivil = estadoCivil.lower()

Browser other questions tagged

You are not signed in. Login or sign up in order to post.