On Sat, Apr 04, 2015 at 11:49:08AM -0500, boB Stepp wrote: > Windows 7, Python 3.4.3 > > This code snippet is "Example 7-13" on page 383 from "Programming > Python, 4th ed." by Mark Lutz : > > import sys > from tkinter import * > > widget = Button(None, > text='Hello event world!', > command=(lambda: print('Hello lambda world!') or sys.exit()))
o_O That's either the most horrible misuse of lambda I've ever seen, or a really cool and rather nifty trick. I'm not sure which :-) > widget.pack() > widget.mainloop() > > My question is about the lambda expression. The author states "...this > version uses an or operator to force two expressions to be run..." I > am not understanding how 'or' causes this to happen. I guess I am > expecting the 'or' to result only in the print running without > executing sys.exit(). But that is not what happens--of course. I tried > substituting 'and' for 'or', but this results in only the print being > run! Obviously I have a significant misunderstanding of what is going > on. Both `or` and `and` are "short-circuit" operators. Here is a truth-table for `a or b`: |a = True False -----------+----------------- b = True | True True False | True False If `a` is true, then `a or b` is true, regardless of whether b is true or false. So we can say that if `a` is true, `a or b` returns `a`. If `a` is false, then `a or b` returns true if, and only if, `b` is true; otherwise it returns false. So we can say that if `a` is false, then `a or b` returns `b`. So we can define our own "or" function like this: def or_ (a, b): if a: return a else: return b Unlike this function version, the `or` operator doesn't evaluate the `b` expression unless needed. So this piece of code: print(msg) or sys.exit() runs like this: (1) Evaluate the expression on the left of the operator: print(msg). (2) That has the side-effect of printing the message, and returns the value None. (3) Is None a true value? If so, `or` can short-circuit, and return it as its result. (4) But None is a false value, so evaluate the expression on the right of the operator: sys.exit() (5) Which has the side-effect of exiting the interpreter. (6) The `or` operator would now return the result of sys.exit(), if it had one; but it doesn't, since the interpreter has just exited. A cleaner example might be this: py> def true(): ... print("calling true") ... return 23 # a true-ish value ... py> def false(): ... print("calling false") ... return 0 # a false-ish value ... py> true() or false() # only the left operand is evaluated calling true 23 py> true() or true() calling true 23 py> false() or true() # both operands are evaluated calling false calling true 23 py> false() or false() calling false calling false 0 The `and` operator is similar, except the truth-table looks like this: |a = True False -----------+----------------- b = True | True False False | False False Again, the right-hand operand is only evaluated if it is needed. This lets us write code like this: if mylist and mylist[0] == spam: eggs() If mylist is empty, then `mylist and ...` doesn't even need to evaluate the right-hand operand, mylist[0] doesn't run and so does not fail. Only if mylist is a truthy value does mylist[0] run. -- Steve _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor