["python","list","set","any"]
Using any() and all() to check if a list contains one set of values or another

My code is for a Tic Tac Toe game and checking for a draw state but I think this question could be more useful in a general sense. I have a list that represents the board, it looks like this: board = [1,2,3,4,5,6,7,8,9] When a player makes a move, the integer they moved on is replaced with their marker ('x' or 'o'). I already have checks in place to look for a winning state. What I can't do is check for a draw state, where none of the list values are integers but a winning state has not been set. The code I have so far: if any(board) != playerOne or any(board) != playerTwo: print 'continue' elif all(board) == playerOne or playerTwo: print 'Draw' The if statement works, the elif does not. I think the problem is my 'or' operator. What I want to check for is: if the every item on the board is either playerOne marker or playerTwo marker. If I were to make the code: elif all(board) == playerOne or all(board) == playerTwo: I would be checking to see if every place on the board was playerOne or every place on the board is playerTwo, which it won't be. So how do I check if the board is taken up by a combination of playerOne markers and playerTwo markers?
Generally speaking: all and any are functions that take some iterable and return True, if in the case of all, no values in the iterable are falsy; in the case of any, at least one value is truthy. A value x is falsy iff bool(x) == False. A value x is truthy iff bool(x) == True. Any non-boolean elements in the iterable are perfectly acceptable — bool(x) maps, or coerces, any x according to these rules: 0, 0.0, None, [], (), [], set(), and other empty collections are mapped to False all other values are mapped to True. The docstring for bool uses the terms 'true'/'false' for 'truthy'/'falsy', and True/False for the concrete boolean values. For example: if all(x > 0 for x in xs) or any(x > 100 for x in xs): # if nothing is zero or something is over a hundred … In your specific code samples: You’ve slightly misunderstood how these functions work. The following does something completely different from what you thought: if any(foobars) == big_foobar: ...because any(foobars) would first be evaluated to either True or False, and then that boolean value would be compared to big_foobar, which generally always gives you False (unless big_foobar coincidentally happened to be the same boolean value). Note: the iterable can be a list, but it can also be a generator or a generator expression (≈ lazily evaluated/generated list), or any other iterator. What you want instead is: if any(x == big_foobar for x in foobars): which basically first constructs an iterable that yields a sequence of booleans—for each item in foobars, it compares the item to the value held by big_foobar, and (lazily) emits the resulting boolean into the resulting sequence of booleans: tmp = (x == big_foobar for x in foobars) then any walks over all items in tmp and returns True as soon as it finds the first truthy element. It's as if you did the following: In [1]: foobars = ['big', 'small', 'medium', 'nice', 'ugly'] In [2]: big_foobar = 'big' In [3]: any(['big' == big_foobar, 'small' == big_foobar, 'medium' == big_foobar, 'nice' == big_foobar, 'ugly' == big_foobar]) Out[3]: True Note: As DSM pointed out, any(x == y for x in xs) is equivalent to y in xs but the latter is more readable, quicker to write and runs faster. Some examples: In [1]: any(x > 5 for x in range(4)) Out[1]: False In [2]: all(isinstance(x, int) for x in range(10)) Out[2]: True In [3]: any(x == 'Erik' for x in ['Erik', 'John', 'Jane', 'Jim']) Out[3]: True In [4]: all([True, True, True, False, True]) Out[4]: False See also: http://docs.python.org/2/library/functions.html#all