1

It is pretty self-explanitory from the code but I want to check if the input is not equal to these values than ask again. I thought this would work but it doesn't and its glitchy, what is a better way to do this?

type=input("Please choose an option: ")
while type.isalpha() == False:
    type=input("Please choose an option: ")
while type != ("a" and "A" and "b" and "B" and "c" or "C"):
    type=input("Please choose an option: ")
Kevin Harrison
  • 335
  • 1
  • 10
  • short explanation: `("a" and "A" and "b" and "B" and "c" or "C")` is evaluated *first*, let's say the result of this is called `x`. Then the conditional is equivalent to `type != x`, which is silly. – user2246674 Oct 03 '13 at 23:51
  • This question gets duplicated an awful lot, but this is the first time I've seen it happen twice in under an hour… – abarnert Oct 03 '13 at 23:53
  • There's certainly a gimmick in here somewhere for some language designer. The meaning that the questioners incorrectly expect is powerfully attractive to novice programmers. – Steve Jessop Oct 03 '13 at 23:55
  • @SteveJessop it exists, in the form of regular expressions, but it's still unwieldy: `if re.match(r'(a|A|b|B|c|C)', type): …` – kojiro Oct 04 '13 at 00:05
  • @kojiro: It also exists with the `in` operator without regexps. (Just because regexp uses the same character for alternation than C happens to use for bitwise or doesn't mean that it's "more or-like" than a different syntax.) – abarnert Oct 04 '13 at 00:15
  • @SteveJessop: I really don't understand why people expect this to work. If you read it in English, it doesn't make any sense. And it seems to be peculiar to Python that people expect this—half the people who ask dups of this are coming to Python from Java or Scheme or some other language that does the exact same thing as Python, and yet they expect Python to do something different… – abarnert Oct 04 '13 at 00:16
  • @abarnert the parallel I was drawing was that the `|` symbol explicitly means *or* in regular expressions. The end result is the same, but there's a semantic difference between "x matches 'a' or 'b' or 'c'" and "x is a member of the set of characters 'abc'". – kojiro Oct 04 '13 at 00:19
  • @abarnert: I'm not sure about this version with `and`, but I'm prety sure the version I with `or` is because in English you can say, "it's a dog or a cat" and it means "(it's a dog) or (it's a cat)". In general in English "X or Y" distributes across the next operator: "Alice or Bob is lying", "The Saints or the Dolphins will go 4-0". – Steve Jessop Oct 04 '13 at 00:21
  • 2
    When you name your variable `type`, you're shadowing the existing builtin function `type()`. It's a bad practice, avoid doing that, it will save you a major headache some day. – rahmu Oct 04 '13 at 00:55
  • @rahmu: Especially good advice given that, from the comments on the answers, it looks like the user has also shadowed `list` and actually run into that headache. – abarnert Oct 04 '13 at 01:10

3 Answers3

4

Simply do while not type in ("a","A","b","B" ...) to check whether type is one of the listed elements.

The code above is, as mentioned in comments, equivalent to while type != someListElement because the and and or are evaluated first.

Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
  • 3
    `not in` is usually more readable than `not … in` – abarnert Oct 03 '13 at 23:53
  • You could also write this `while type not in set('ABCabc')` – kojiro Oct 03 '13 at 23:56
  • 1
    Or even just `while type not in 'ABCabc'`. Strings are iterable and it's short, so the conversion to a set isn't going to save you much time. – reem Oct 04 '13 at 00:07
  • Thankyou! This helped a lot! This was actually for my homework due tomorrow and this was the last piece I needed finished! – Kevin Harrison Oct 04 '13 at 00:07
  • Well, SO is _not_ for homework. Anyway. – Alexander Gessler Oct 04 '13 at 00:10
  • This was for my computer science class and I was having trouble with this part and now I understand and learned something new. Thats what Stackoverflow is all about. – Kevin Harrison Oct 04 '13 at 00:14
  • True, but people don't like to get the feeling that they are just doing your homework. A classic trick is: don't tell them! :-) – Alexander Gessler Oct 04 '13 at 00:24
  • 1
    @AlexanderGessler Actually, that isn't really the official position of StackOverflow on homework. [This isn't either](http://meta.stackexchange.com/questions/10811/how-do-i-ask-and-answer-homework-questions/10812#10812), but it's widely accepted. – kojiro Oct 04 '13 at 00:28
  • 1
    @sortfiend: not really, because when the RHS is a string `in` tests substring, not membership. So `'AB' in 'ABCabc'` is True. – Steve Jessop Oct 04 '13 at 00:28
  • 2
    @SteveJessop: Of course a user isn't likely to type `Ca` when asked to type a letter, and in a real program it might be nice to test for `len(type) != 1` and `type not in 'ABCabc'` so you can give different error messages ("Only one letter, if you please" and "Since when is '%s' an A, B, or C, dumbass?"). – abarnert Oct 04 '13 at 00:57
  • @abarnert: Maybe I'm a special case, but I'm perfectly capable of typoing two letters when asked for one. But separate tests with separate error messages is always nice. – Steve Jessop Oct 04 '13 at 01:01
  • @SteveJessop: That's exactly why I gave a polite message for the error Io am likely to do myself. :) – abarnert Oct 04 '13 at 01:09
1

You would need to write:

while (type != "a" and type !="A" and type !="b" and type !="B" and type !="c" or type !="C"):
Tommy
  • 12,588
  • 14
  • 59
  • 110
1

I think the simplest solution would be to use

type = raw_input("Please choose an option: ")
while type not in list('AaBbCc'):
    type = raw_input("Please choose an option: ")

list will convert from a string to a list of single-character strings, which you can then test for inclusion using in. I don't think you need the test for isalpha, because everything you're checking for is already a letter.

Also, you should always use raw_input rather than input to get user input, because raw_input always returns a string, while input tries to eval what the user enters, which is not what you want.

(This is assuming you're using Python 2. If you're using Python 3, input is what raw_input was before, and raw_input no longer exists.)

colevk
  • 670
  • 1
  • 5
  • 10
  • Yes, but underneath my code I have validations like this. if type == ("a") or type ==("A"): – Kevin Harrison Oct 04 '13 at 00:38
  • I did try your method but if I type a letter that isn't in the "AaBbCc" for example "d", it gives a typeerror saying that list function is not callable. I tried to just put it without list() and it worked perfectly like that! Thankyou! I also took isalpha out because you're correct! This looks a bit more clean :) Thanks – Kevin Harrison Oct 04 '13 at 00:41
  • 1
    @KevinHarrison: regarding the `TypeError`, you may have used `list` as a variable name earlier in the function/program. If so, stop it, don't use Python builtins as variable names. The same goes for `type`, although you'll probably find that you need the `type` builtin a *lot* less than you need the `list` builtin. – Steve Jessop Oct 04 '13 at 00:48
  • `list` should be a built-in function. Are you defining a variable called `list` earlier in your code? – colevk Oct 04 '13 at 00:49
  • Actually no, list isn't declared as a variable although I have a variable called list2 because I knew that if I called it list, I couldn't use list() – Kevin Harrison Oct 04 '13 at 03:34