[Python-ideas] while conditional in list comprehension ?? (original) (raw)
Oscar Benjamin oscar.j.benjamin at gmail.com
Thu Jan 31 01:37:23 CET 2013
- Previous message: [Python-ideas] while conditional in list comprehension ??
- Next message: [Python-ideas] while conditional in list comprehension ??
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 30 January 2013 22:56, Steven D'Aprano <steve at pearwood.info> wrote:
On 31/01/13 05:05, Oscar Benjamin wrote:
On 30 January 2013 17:56, Yuriy Taraday<yorik.sar at gmail.com> wrote:
On Wed, Jan 30, 2013 at 1:46 PM, Wolfgang Maier <wolfgang.maier at biologie.uni-freiburg.de> wrote:
your condition is 'partial(lt,50)', but this is not met to begin with and results in an empty list at least for me. Have you two actually checked the output of the code or have you just timed it? Yeah. Shame on me. You're right. My belief in partial and operator module has been shaken. This is why I prefer this stop() idea to any of the takewhile() versions: regardless of performance it leads to clearer code, that can be understood more easily. Funny you say that, clarity of code and ease of understanding is exactly why I dislike this stop() idea. 1) It does not work with list, dict or set comprehensions, only with generator expressions. So if you need a list, dict or set, you have to avoid the obvious list/dict/set comprehension.
That's true. I would prefer it if a similar effect were achievable in these cases.
2) It is fragile: it is easy enough to come up with examples of the above that appear to work: [i for i in range(20) if i < 50 or stop()] # appears to work fine [i for i in range(20) if i < 10 or stop()] # breaks
As I said I would prefer a solution that would work for list comprehensions but there isn't one so the stop() method has to come with the caveat that it can only be used in that way. That said, I have become used to using a generator inside a call to dict() or set() (since the comprehensions for those cases were only recently added) so it doesn't seem a big problem to rewrite the above with calls to list().
You are right, though, that a bug like this would be problematic. If the StopIteration leaks up the call stack into a generator that is being for-looped then it creates a confusing debug problem (at least it did the first time I encountered it).
3) It reads wrong for a Python boolean expression. Given an if clause: if cond1() or cond2() you should expect that an element is generated if either cond1 or cond2 are true. When I see "if cond1() or stop()" I don't read it as "stop if not cond1()" but as a Python bool expression, "generate an element if cond1() gives a truthy value or if stop() gives a truthy value".
Again I would have preferred 'else break' or something clearer but this seems the best available (I'm open to suggestions).
This "if cond or stop()" is a neat hack, but it's still a hack, and less readable and understandable than I expect from Python code.
It is a hack (and I would prefer a supported method) but my point was that both you and Yuriy wrote the wrong code without noticing it. You both posted it to a mailing list where no one else noticed until someone actually tried running the code. In other words it wasn't obvious that the code was incorrect just from looking at it.
This one looks strange but if you knew what stop() was then you would understand it: list(x for x in range(100) if x < 50 or stop())
This one is difficult to mentally parse even if you understand all of the constituent parts: [x for x in takewhile(partial(lt, 50), range(100))]
Oscar
- Previous message: [Python-ideas] while conditional in list comprehension ??
- Next message: [Python-ideas] while conditional in list comprehension ??
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]