Re: [Tutor] Functional Programming in Python
On Sat, Apr 04, 2015 at 09:53:28PM -0400, WolfRage wrote: > > So I was surprised I did not get more feedback on my abused coroutine, > maybe that is good or bad, not sure. Perhaps people didn't understand it. Or see it :-) > Any ways I am on to trying to make that coroutine act more like the > State Pattern from Gang of Four. And well reading this: > http://gameprogrammingpatterns.com/state.html Now you're fighting the paradigm. Functional programming works best for code that avoids side-effects. But changes of state are naturally a side-effect! I was sitting, now I am walking. It's still me, but my state is different. Now of course you can emulate state changes using purely functional code, but its harder and less efficient. > I am not sure how to do this: > class Heroine > { > public: > virtual void handleInput(Input input) > { > state_->handleInput(*this, input); > } > > virtual void update() > { > state_->update(*this); > } > > // Other methods... > private: > HeroineState* state_; > }; > > (Pointing to the different classes. Since C++ has virtual methods but > Python does not?) in Python? Do I just reference the new method? Because > state_ will always be the correct object? Hmmm, I'm not sure, but I think that we would say that *all* Python methods are virtual in C++ terms. They are all resolved at runtime. There are a few ways we might do this in Python. class Heroine: def __init__(self): self.state = "standing" # Or use an Enum in Python 3.4 def jump(self): if self.state == "standing": self.state = "jumping" ... elif self.state == "jumping": pass # Dispatch table of keys to actions. KEYMAP = {'b': jump, 'd': duck, 'f': run, ... } def handle_keypress(self, key): method = self.KEYMAP.get(key, None) if method: method(self) We look up the key press, and get a reference to the method itself, not the name of the method. (Or None.) We then call that method by providing self as the first argument. Nice and easy. It's so easy that I'm not sure if it's even worth discussing alternatives. Another alternative might be to use delegation, or object composition. Give the Heroine class all the methods which don't change. For the methods which do change, create a separate FooState class for each state: class JumpingState: def jump(self): pass def duck(self): ... class RunningState: ... class Heroine: def __init__(self): self.state = StandingState() # Dispatch table of keys to method names. KEYMAP = {'b': 'jump', 'd': 'duck', 'f': 'run', ... } def handle_keypress(self, key): name = self.KEYMAP.get(key, None) if name: newstate = getattr(self.state, name)() if newstate: self.state = newstate() Methods of the state object can signal a change of state by returning the class representing the new state. Otherwise, they can return None to signal no change of state. Here is how we might do this using inheritence instead of composition. Start with a base class and a bunch of default methods which conditionally raise: class BaseHeroine: def jump(self): if self.__class__ is BaseHeroine: raise RuntimeError def run(self): if self.__class__ is BaseHeroine: raise RuntimeError def duck(self): if self.__class__ is BaseHeroine: raise RuntimeError # Dispatch table of keys to method names. KEYMAP = {'b': 'jump', 'd': 'duck', 'f': 'run', ... } def handle_keypress(self, key): name = self.KEYMAP.get(key, None) if name: getattr(self.state, name)() Now have a bunch of subclasses, one for each state. Override only the methods you need. (Remember, the default behaviour for each method is to do nothing, if called from a subclass. They only raise if called from the base class.) class JumpHeroine(BaseHeroine): ... class StandHeroine(BaseHeroine): ... class RunHeroine(BaseHeroine): ... Now create an instance, and set its state: heroine = BaseHeroine() heroine.__class__ = StandHeroine State transitions are managed by *changing the instance's class*. Methods can do that themselves: def spam(self): self.__class__ = RunHeroine # Don't instantiate the class. print("Spam spam spam lovery spam") Now, I haven't tested any of the above code, but here is a short and simple demonstration showing that it does work: py> class X: ... def display(self): ... print("in X") ... def method(self): ... self.display() ... print(self, type(self), self.__class__) ... py> class Y(X): ... def display(self): .
Re: [Tutor] Functional Programming in Python
On 04/04/2015 09:53 PM, WolfRage wrote: (Pointing to the different classes. Since C++ has virtual methods but Python does not?) I'd say that all methods in Python are virtual, except for those which are classmethod or staticmethod. -- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
On 04Apr2015 22:45, boB Stepp wrote: On Sat, Apr 4, 2015 at 6:55 PM, Alan Gauld wrote: lambda : all([print('Hello lambda world!'), sys.exit()] ) Well, now I am curious as to why the "all" form evaluates BOTH elements. Apparently it does not apply the short-circuit logic we have been discussing, or it would stop evaluating after the print statement return. Why is that? Because the list/tuple is constructed entirely before all() is called. All() operates only on the final values. Cheers, Cameron Simpson Yesterday, I was running a CNC plasma cutter that's controlled by Windows XP. This is a machine that moves around a plasma torch that cuts thick steel plate. �A "New Java update is available" window popped up while I was working. �Not good. - John Nagle ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
On Sat, Apr 4, 2015 at 6:55 PM, Alan Gauld wrote: > On 04/04/15 22:57, boB Stepp wrote: >> >> On Sat, Apr 4, 2015 at 3:35 PM, Alan Gauld >> wrote: >>> >>> He could have done it in various other ways too: >>> >>> eg. >>> lambda : all(print('Hello lambda world!'), sys.exit() ) >> >> >> Is this what you meant? Because print will always return False. Or did >> you actually mean: >> >> lambda: any(print('Hello lambda world!'), sys.exit()) > > > any() would be more obvious, but in my interpreter > both any() and all() evaluate both functions before > testing the results. At least they do once you > fix the TypeError : they should be in a list/tuple... > > lambda : all([print('Hello lambda world!'), sys.exit()] ) Well, now I am curious as to why the "all" form evaluates BOTH elements. Apparently it does not apply the short-circuit logic we have been discussing, or it would stop evaluating after the print statement return. Why is that? -- boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Functional Programming in Python
On Thu, Apr 02, 2015 at 12:18:28PM -0400, WolfRage wrote: > These are just some questions that I have regarding the topic of > Functional Programming. I am working towards a more functional approach > to programming but acknowledge that it is far from Functional, > especially since this is mostly impossible in Python. You might like to read this: https://codewords.recurse.com/issues/one/an-introduction-to-functional-programming I'm not sure whether I agree with the author, but it's worth reading. -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
On Sun, Apr 05, 2015 at 12:55:16AM +0100, Alan Gauld wrote: > On 04/04/15 22:57, boB Stepp wrote: > >On Sat, Apr 4, 2015 at 3:35 PM, Alan Gauld > >wrote: > >>He could have done it in various other ways too: > >> > >>eg. > >>lambda : all(print('Hello lambda world!'), sys.exit() ) > > > >Is this what you meant? Because print will always return False. Or did > >you actually mean: > > > >lambda: any(print('Hello lambda world!'), sys.exit()) > > any() would be more obvious, but in my interpreter > both any() and all() evaluate both functions before > testing the results. At least they do once you > fix the TypeError : they should be in a list/tuple... > > lambda : all([print('Hello lambda world!'), sys.exit()] ) That's because the sys.exit() call leaves the interpreter because any() gets a chance to raise TypeError :-) Your code: lambda: all(print('Hello lambda world!'), sys.exit()) is equivalent to this: a = print('Hello lambda world!') b = sys.exit() # Goodbye cruel world! all(a, b) # this never gets called so you could replace the call to all() with any(), or len(), or zxcvbnm() if you like, it makes no difference at all. The moral equivalent of the original `or` trick would be something like this: any(spam() for spam in [lambda: print("Hello lambda world!"), os.exit]) which now avoids calling os.exit until necessary. E.g. we might write a function which prints a message, then has a 50% chance of exiting: any(spam() for spam in [lambda: print("Hello lambda world!"), lambda: random.random() > 0.5, lambda: print("Goodbye cruel world!"), os.exit] ) will always print Hello, and fifty percent of the time will print Goodbye then exit, otherwise it will return True. -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
On 05Apr2015 03:34, Steven D'Aprano wrote: On Sat, Apr 04, 2015 at 11:49:08AM -0500, boB Stepp wrote: widget = Button(None, text='Hello event world!', command=(lambda: print('Hello lambda world!') or sys.exit())) 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 :-) I think it is misuse. When I need to run two functions like that I tend to use a tuple: lambda: (f1(), f2()) Since Python evaluates left to right, these functions are called f1 first, then f2. Using "or" introduces a reliance on f1 returning a falsish value. Dodgy and unreliable. Not to mention conflating the supposed Boolean value computed by the expression with the program's purpose. Like others, I agree it is generally better to define a function more normally and just name in instead of inlining a lambda. But sometimes (rarely) that makes for harder to read code structure (though easier to read function internals). Anyway, faced with a desire to use a lambda here, I would choose a tuple. Cheers, Cameron Simpson This is my simple religion. There is no need for temples; no need for complicated philosophy. Our own brain, our own heart is our temple; the philosophy is kindness. - Dalai Lama ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
On Sat, Apr 04, 2015 at 02:21:19PM -0500, boB Stepp wrote: > To my mind, would: > > def quit(): > print('Hello lambda world!') > sys.exit() > > and: > > widget = Button(None, text='Hello event world!', command=quit) > > be preferable Python style? Hell yes! Using `or` to run functions purely for their side-effects (in this case, printing and exiting) makes a nice trick, but I wouldn't use for real. On the other hand, using `or` for its value is perfectly acceptable. E.g. one common idiom might be to iterate over something which might be None: for value in maybe_list or []: ... If `maybe_list` is a non-empty list, it is used; if it is an empty list, the second operand (also an empty list) is used, but that's okay since they are both empty lists; and if it is None, then the second operand is used instead. This is a reasonable idiom to use, and prior to Python 2.5 it was the closest thing the language had to a "ternary if operator". These days, the `or` idiom is less common except in old code or code that has to run on Python 2.4 or older. Instead, we might write: for value in (maybe_list if maybe_list is not None else []): ... I'm not entirely sure that's an improvement :-) -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Functional Programming in Python
So I was surprised I did not get more feedback on my abused coroutine, maybe that is good or bad, not sure. Any ways I am on to trying to make that coroutine act more like the State Pattern from Gang of Four. And well reading this: http://gameprogrammingpatterns.com/state.html I am not sure how to do this: class Heroine { public: virtual void handleInput(Input input) { state_->handleInput(*this, input); } virtual void update() { state_->update(*this); } // Other methods... private: HeroineState* state_; }; (Pointing to the different classes. Since C++ has virtual methods but Python does not?) in Python? Do I just reference the new method? Because state_ will always be the correct object? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
On 04/04/15 22:57, boB Stepp wrote: On Sat, Apr 4, 2015 at 3:35 PM, Alan Gauld wrote: He could have done it in various other ways too: eg. lambda : all(print('Hello lambda world!'), sys.exit() ) Is this what you meant? Because print will always return False. Or did you actually mean: lambda: any(print('Hello lambda world!'), sys.exit()) any() would be more obvious, but in my interpreter both any() and all() evaluate both functions before testing the results. At least they do once you fix the TypeError : they should be in a list/tuple... lambda : all([print('Hello lambda world!'), sys.exit()] ) So this is not unusual for Python. BTW, what are some of the other languages where this type of expression might be commonly used? It's sometimes used in Turbo Pascal/Delphi and also in Perl (a lot!). I think I've seen it used in PHP too. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
On 04/04/2015 17:49, 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())) 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. Thanks! The print function in Python 3 always returns None, which is a false value. As we're talking 'or' here the second part wills always get run, hence in this case sys.exit() gets called. I'd try the same thing by using your own function. def myprint(mystr): print(mystr) return 0 Substitute print in the lambda with myprint and try it, then replace the '0' with a '1' and see what happens. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
On 04/04/2015 05:57 PM, boB Stepp wrote: On Sat, Apr 4, 2015 at 3:35 PM, Alan Gauld wrote: He could have done it in various other ways too: eg. lambda : all(print('Hello lambda world!'), sys.exit() ) Is this what you meant? Because print will always return False. Or did you actually mean: lambda: any(print('Hello lambda world!'), sys.exit()) But the OR style is established as a kind of idiom, not just in Python but several other languages too. So this is not unusual for Python. BTW, what are some of the other languages where this type of expression might be commonly used? I don't think I've ever seen it used in Python. But it's quite common in Perl scripts and bash scripts that I've seen. In the case of bash, one might do something like: prog1 && prog2 and prog2 gets executed only if prog1 had a successful completion -- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
On Sat, Apr 4, 2015 at 3:35 PM, Alan Gauld wrote: > He could have done it in various other ways too: > > eg. > lambda : all(print('Hello lambda world!'), sys.exit() ) Is this what you meant? Because print will always return False. Or did you actually mean: lambda: any(print('Hello lambda world!'), sys.exit()) > But the OR style is established as a kind of idiom, > not just in Python but several other languages too. So this is not unusual for Python. BTW, what are some of the other languages where this type of expression might be commonly used? -- boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
On 04/04/15 17:49, boB Stepp wrote: widget = Button(None, text='Hello event world!', command=(lambda: print('Hello lambda world!') or sys.exit())) am not understanding how 'or' causes this to happen. I guess I am expecting the 'or' to result only in the print running without This is explained in more detail in the functional programming topic of my tutorial. It's called short circuit evaluation of boolean expressions if you want to look it up on wikipedia or elsewhere. The short version is that to evaluate an OR Python looks at the first expression and if its true it returns the result - since any single True expression makes the OR true too. If the first expression is false-like (eg None returned from a print() ) then it must evaluate the second expression to be sure of the overall OR result. So by putting a print() which returns None, first Lutz ensures the second expression is also evaluated. He could have done it in various other ways too: eg. lambda : all(print('Hello lambda world!'), sys.exit() ) But the OR style is established as a kind of idiom, not just in Python but several other languages too. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
> > To my mind, would: > > def quit(): > print('Hello lambda world!') > sys.exit() > > and: > > widget = Button(None, text='Hello event world!', command=quit) > > be preferable Python style? > Yes, I'd prefer this much more, compared to the original. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Request review: A DSL for scraping a web page
On Thu, Apr 2, 2015 at 2:49 PM, Albert-Jan Roskam wrote: > > - > On Thu, Apr 2, 2015 1:17 PM CEST Alan Gauld wrote: > >>On 02/04/15 12:09, Dave Angel wrote: >> >>> Ah, Jon Bentley (notice the extra 'e'). I should dig out my *Pearls >>> books, and have a trip down memory lane. I bet 95% of those are still >>> useful, even if they refer to much earlier versions of language(s). >> >>Yes, the Pearls books should be required reading for all new programmers. The >>lessons are pretty timeless, it's only the >>languages that change - and most of his examples seem to be >>in a kind of pseudo Pascal dialect rather than real code anyway. >> >>I believe they've been re-released as a single volume now. > > Is this the book you are referring to? > http://www.amazon.com/Programming-Pearls-2nd-Edition-Bentley/dp/0201657880 This thread inspired me to order both books from Amazon. The one linked to above by Alan is an expanded and somewhat rewritten edition of the original. It does NOT include "More Programming Pearls". I just today received my copy of "Programming Pearls, 2nd ed." To quote from part of the author's preface of "Programming Pearls, 2nd ed.": "To Readers of the First Edition I hope that your first response as you thumb through this edition of the book is, 'This sure looks familiar.' A few minutes later, I hope that you'll observe, 'I've never seen that before.' This version has the same focus as the first edition, but is set in a larger context. Computing has grown substantially in important areas such as databases, networking and user interfaces. Most programmers should be familiar users of such technologies. At the center of each of those areas, though, is a hard core of programming problems. Those programs remain the theme of this book. This edition of the book is a slightly larger fish in a much larger pond. ..." HTH -- boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
On Sat, Apr 4, 2015 at 12:34 PM, Steven D'Aprano wrote: > 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 :-) Re-reading the paragraph relevant to Mr. Lutz's example, perhaps I should quote the full paragraph: "This code is a bit tricky because lambdas can contain only an expression; to emulate the original script, this version uses an or operator to force two expressions to be run (print works as the first, because it's a function call in Python 3.X--we don't need to resort to using sys.stdout directly)." I think the key thought of the author here is he showing how to rewrite an earlier example that explicitly defines a quit() function, which both prints and then exits the program, to using a lambda expression. I don't think his intent is to say that the lambda expression is to be preferred (Or is he?). To my mind, would: def quit(): print('Hello lambda world!') sys.exit() and: widget = Button(None, text='Hello event world!', command=quit) be preferable Python style? boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
On Sat, Apr 4, 2015 at 12:34 PM, Steven D'Aprano wrote: > 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 :-) Now that I have read (and hopefully understand) your entire response, I am wondering the same thing in the sense that my understanding of Python's intent is for clearly readable code and this usage isn't clear without some thought (At least for me!). >> 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 I get and understand the short-circuit logic. This isn't what got me! [...] > 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. This was my 'gotcha'. I forgot (but knew) that print functions return None. Perhaps this constant switching back and forth between using Python 2 at work and Python 3 at home is addling my brain? Also, even if I had recalled the return of None, I might have missed that the "side-effect" still occurs, i.e., the actual printing. [...] > The `and` operator is similar, except the truth-table looks like this: > > >|a = True False > ---+- > b = True |True False > False |False False And of course since print returns None, the short-circuit evaluation causes the sys.exit() never to be seen. Even though I snipped out most of your very well-constructed examples, Steve, I have to say, you have a knack for making things abundantly clear! You tutor very well, indeed, and I am appreciative! -- boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Use of "or" in a lambda expression
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
[Tutor] Use of "or" in a lambda expression
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())) 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. Thanks! -- boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Request review: A DSL for scraping a web page
Joe Farro gmail.com> writes: > indentation doesn't (always) reflect the hierarchy of the data being > generated, which seems more clear. Meant to say: However, the indentation doesn't (always) reflect the hierarchy of the data being generated, which seems more clear **in the bs4 version**. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Request review: A DSL for scraping a web page
Joe Farro gmail.com> writes: > > Thanks, Peter. > > Peter Otten <__peter__ web.de> writes: > > > Can you give a real-world example where your DSL is significantly cleaner > > than the corresponding code using bs4, or lxml.xpath, or lxml.objectify? Peter, I worked up what I hope is a fairly representative example. It scrapes metadata from the 10 newest web-scraping questions on stackoverflow. It's done with bs4 and take. https://github.com/tiffon/take-examples/tree/master/samples/stackoverflow I've posted on the bs4 discussion group asking for feedback on the bs4 version to make sure it's up to snuff. (The post is in new-member purgatory, at the moment.) In my opinion, the fact that take lacks an ability to define sub-routines is a brutal deficiency. (As compared to defining functions like `get_poster_details()` and `get_comment_activity()` in the bs4 version.) On the bright side, I do like that the indentation of the take templates semi-reflect the structure of the HTML document. However, the indentation doesn't (always) reflect the hierarchy of the data being generated, which seems more clear. Feedback is definitely welcome. Thanks again! ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor