Rules for assigning truth values to conditions ============================================== We've discussed the rules Python uses to decide whether an expression tested as a condition by if or while will be considered true. To recap briefly, here are the rules to determine whether an item of a given type is considered true: Numbers: true if not zero. ------- # a is a number. if a: <---> if a != 0: Strings: true if not empty. ------- # s is a string if s: <---> if len(s): <---> if len(s) != 0: if s: <---> if s != "": Sequence types in general: true if not empty. ------------------------- (Includes strings, lists, and tupes.) if L: <---> if len(L): <----> if len(L) != 0: Dictionaries: true if not empty. ------------ if d: <---> if d.keys(): <---> if len(d.keys()): <---> etc. Objects: true if not None. ------- if o: <---> if o is not None: Functions, types, and classes: always true. ----------------------------- # f is a function if f: <---> if 1: # t is a type if t: <---> if 1: # c is a class if c: <---> if 1: However, do not confuse functions with function calls: # f is a function if f(): <---> x = f(), and then if x: Comparison operators ==================== (a > b) == 1 if a is greater than b (true) 0 otherwise (false) (a < b) == 1 if a is less than b (true) 0 otherwise (false) (a == b) == 1 if a is equal to b (true) 0 otherwise (false) (a != b) == 1 if a is not equal to b (true) 0 otherwise (false) (a <> b) == (a != b) etc. Boolean operators ================= These allow you to express complex logical conditions which may involve more than one test. Here are a few examples: if patently_offensive() and lacking_slapp_value() and purient(): print "obscene" else: print "not obscene" if (employer == "EFF") or (employer == "ACLU"): print "cool" else: print "sketchy" if (temp < 0) or (temp > 100): print "water is not a liquid at this temperature" else: print "water is a liquid at this temperature" if (temp => 0) and (temp <= 100): print "water is a liquid at this temperature" else: print "water is not a liquid at this temperature" x and y ---> true if x and y are both true (false otherwise) x or y ---> true if x or y is true (or both are true) (false otherwise) not x ---> true if x is false (and false if x is true) You may want to use parentheses in order to remove possible ambiguities. (Python has rules for removing these ambiguities, but Python's rules might not remove ambiguities the way you intended). For example, if a and b or c: might mean several different things to different humans: if (a and b) or c: if a and (b or c): and other combinations are possible in more complex expressions. (These meanings yield different results, for example, if a is 0 and c is 1. The first interpretation would then make the expression false; the second interpretation would make it true.) To Python, it happens to mean if (a and b) or c: but you might prefer to write the parentheses rather than memorizing the rules which account for this. Optional appendix: Bitwise operators ==================================== "&" does bitwise AND; "|" does bitwise OR. "~" does bitwise NOT. "^" does bitwise XOR. I doubt that any of these will be necessary for this class, so you don't need to worry about learning them. They are mainly used by C programmers (in fact, the symbols are borrowed from C) and by some people trying to do fast arithmetic (e.g. for cryptography). The quick description of the bitwise operators is as follows: a bitwise operator converts both operands to a binary representation and then calculates a new number by applying the logical operation specified to each pair of bits. So binary 0011 (the number 3) bitwise-ANDed with binary 0101 (the number 5) yields binary 0001 (the number 1). For high-level programming, it is very rare that you'd find a need to use these. One interesting application: def odd(n): return n & 1 Do you see why? Optional appendix: short-circuit evaluation =========================================== The Boolean operators and, or, and not actually do yield values which you can assign to variables, print out, do arithmetic with, use as the return value of a function, etc. We gave a description of the conditions under which the values they yield will be true or false, but we didn't say exactly what those values were. This leaves open many possibilities, since so many things are considered "true" within Python. Perhaps ("hello" and "there") -- which we know is true -- equals 3, or perhaps it equals "Guido". (Both 3 and "Guido" are considered true in Python.) It turns out that they work this way: x and y ------- if x: return y else: return x x or y ------ if x: return x else: return y not x ----- if x: return 0 else: return 1 The rules given above are examples of what's called short-circuit evaluation rules: if the first operand for an "and" is false, it is returned without even looking at the second operand. If the first operand for an "or" is true, it is returned without even looking at the second operand. Otherwise, the second operand is returned. Do you see why these rules make "and" and "or" work properly? By knowing the short-circuit evaluation rules, you can sometimes write more concise programs and avoid the need for an "if". (Some programmers may think you're showing off. Using the short-circuit rules is never _necessary_.) Can you think of an example where a short-circuit rule can make a program more concise?