Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #82752 > unrolled thread

Re: List Comprehensions

Started byChris Angelico <rosuav@gmail.com>
First post2014-12-22 17:06 +1100
Last post2014-12-22 09:45 -0800
Articles 6 — 3 participants

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: List Comprehensions Chris Angelico <rosuav@gmail.com> - 2014-12-22 17:06 +1100
    Re: List Comprehensions Roy Smith <roy@panix.com> - 2014-12-22 08:07 -0500
      Re: List Comprehensions Chris Angelico <rosuav@gmail.com> - 2014-12-23 00:21 +1100
        Re: List Comprehensions Rustom Mody <rustompmody@gmail.com> - 2014-12-22 06:58 -0800
          Re: List Comprehensions Chris Angelico <rosuav@gmail.com> - 2014-12-23 02:07 +1100
            Re: List Comprehensions Rustom Mody <rustompmody@gmail.com> - 2014-12-22 09:45 -0800

#82752 — Re: List Comprehensions

FromChris Angelico <rosuav@gmail.com>
Date2014-12-22 17:06 +1100
SubjectRe: List Comprehensions
Message-ID<mailman.17109.1419228400.18130.python-list@python.org>
On Mon, Dec 22, 2014 at 4:42 PM, Ganesh Pal <ganesh1pal@gmail.com> wrote:
> (a)  I was trying to reduce the below piece of code using List comprehension
> ? Any suggestion please let me know
>
>
>      for opt in options:
>           opt['result'] = Queue.Queue()
>           tmp_thread = pause.Thread(opt)
>           threads.append(tmp_thread)
>            tmp_thread.start()
>
> (b)    Is there anything that I need to consider while using list
> comprehension with threads ?

Your code is doing several things at once, so it's probably not worth
trying to turn it into a comprehension. I don't think it needs to be
shortened, anyway; looks fine to me.

ChrisA

[toc] | [next] | [standalone]


#82768

FromRoy Smith <roy@panix.com>
Date2014-12-22 08:07 -0500
Message-ID<roy-8A482E.08070922122014@news.panix.com>
In reply to#82752
In article <mailman.17109.1419228400.18130.python-list@python.org>,
 Chris Angelico <rosuav@gmail.com> wrote:

> On Mon, Dec 22, 2014 at 4:42 PM, Ganesh Pal <ganesh1pal@gmail.com> wrote:
> > (a)  I was trying to reduce the below piece of code using List comprehension
> > ? Any suggestion please let me know
> >
> >
> >      for opt in options:
> >           opt['result'] = Queue.Queue()
> >           tmp_thread = pause.Thread(opt)
> >           threads.append(tmp_thread)
> >            tmp_thread.start()
> >
> > (b)    Is there anything that I need to consider while using list
> > comprehension with threads ?
> 
> Your code is doing several things at once, so it's probably not worth
> trying to turn it into a comprehension. I don't think it needs to be
> shortened, anyway; looks fine to me.

I pretty much agree with Chris.  If I were to refactor this, however, I 
would probably pull the body of the loop out into a function, then it 
might make sense to do the accumulation of threads in a comprehension:

def init_thread(opt):
   opt['result'] = Queue.Queue()
   thread = pause.Thread(opt)
   thread.start()
   return thread

threads = [init_thread(opt) for opt in options]

But, really, I think the way you had it originally was cleaner.

[toc] | [prev] | [next] | [standalone]


#82771

FromChris Angelico <rosuav@gmail.com>
Date2014-12-23 00:21 +1100
Message-ID<mailman.17118.1419254490.18130.python-list@python.org>
In reply to#82768
On Tue, Dec 23, 2014 at 12:07 AM, Roy Smith <roy@panix.com> wrote:
> def init_thread(opt):
>    opt['result'] = Queue.Queue()
>    thread = pause.Thread(opt)
>    thread.start()
>    return thread
>
> threads = [init_thread(opt) for opt in options]

If this is, indeed, just initializing the threads, then this might
make sense. Or alternatively, if you could subclass threading.Thread
and do all the work in __init__, then you could simply construct them
all:

class whatever(thread.Thread):
    def __init__(self, opt):
        self.queue = Queue.Queue()
        self.opt = opt
        super().__init__()
        self.start()

threads = [whatever(opt) for opt in options]

Just as long as you can come up with a sane name for the class, or the
initializer function, that makes sense without the list comp.

Incidentally, this is part of what I was saying about side effects
being okay in a list comp; either Roy's or my examples here would be a
list comp that has the side effect of starting a bunch of threads, and
I don't see it as being at all problematic. Just don't use a list comp
for _just_ the side effects.

ChrisA

[toc] | [prev] | [next] | [standalone]


#82775

FromRustom Mody <rustompmody@gmail.com>
Date2014-12-22 06:58 -0800
Message-ID<b1bccab6-7025-41fd-b0a1-d19e1fef41da@googlegroups.com>
In reply to#82771
On Monday, December 22, 2014 6:52:12 PM UTC+5:30, Chris Angelico wrote:
> On Tue, Dec 23, 2014 at 12:07 AM, Roy Smith wrote:
> > def init_thread(opt):
> >    opt['result'] = Queue.Queue()
> >    thread = pause.Thread(opt)
> >    thread.start()
> >    return thread
> >
> > threads = [init_thread(opt) for opt in options]
> 
> If this is, indeed, just initializing the threads, then this might
> make sense. Or alternatively, if you could subclass threading.Thread
> and do all the work in __init__, then you could simply construct them
> all:
> 
> class whatever(thread.Thread):
>     def __init__(self, opt):
>         self.queue = Queue.Queue()
>         self.opt = opt
>         super().__init__()
>         self.start()
> 
> threads = [whatever(opt) for opt in options]
> 
> Just as long as you can come up with a sane name for the class, or the
> initializer function, that makes sense without the list comp.
> 
> Incidentally, this is part of what I was saying about side effects
> being okay in a list comp; either Roy's or my examples here would be a
> list comp that has the side effect of starting a bunch of threads, and
> I don't see it as being at all problematic.

I see it as "Ewww!!!"

If you consider side-effecting comprehensions as kosher,
then a next conclusion is naturally going to be that
multiple generator comprehensions are confusing and therefore
not kosher -- a very unfortunate conclusion IMHO.

Steven's

> results = [function(item) for item in items] 

> If the called function has side-effects, a list comp is not a 
> good solution.

> If you don't care about the results, a list comp is not a good solution.

should be standard fare for beginners beginners befuddled by
comprehensions

To the OP:

Comprehensions are not for-statements any more than
conditional expressions are if-statements.
In both cases you want the first for the value, the second for the effect.

Its another matter that you can usually refactor one into the other.

The larger context of your code is not visible so cant elaborate 
more on that now...

[toc] | [prev] | [next] | [standalone]


#82776

FromChris Angelico <rosuav@gmail.com>
Date2014-12-23 02:07 +1100
Message-ID<mailman.17120.1419260860.18130.python-list@python.org>
In reply to#82775
On Tue, Dec 23, 2014 at 1:58 AM, Rustom Mody <rustompmody@gmail.com> wrote:
> If you consider side-effecting comprehensions as kosher,
> then a next conclusion is naturally going to be that
> multiple generator comprehensions are confusing and therefore
> not kosher -- a very unfortunate conclusion IMHO.

Why does that follow? What has that to do with side effects?

ChrisA

[toc] | [prev] | [next] | [standalone]


#82794

FromRustom Mody <rustompmody@gmail.com>
Date2014-12-22 09:45 -0800
Message-ID<513e14f1-cde3-4564-bdb6-285f55969a85@googlegroups.com>
In reply to#82776
On Monday, December 22, 2014 8:37:50 PM UTC+5:30, Chris Angelico wrote:
> On Tue, Dec 23, 2014 at 1:58 AM, Rustom Mody wrote:
> > If you consider side-effecting comprehensions as kosher,
> > then a next conclusion is naturally going to be that
> > multiple generator comprehensions are confusing and therefore
> > not kosher -- a very unfortunate conclusion IMHO.
> 
> Why does that follow? What has that to do with side effects?

A comprehension means two things

1. There is the standard de-sugaring in terms of for-loops given in the docs 
that Steven repeated above.

2.There is this picture (needs to be seen in fix-pitch font)

[f(x) for x in [x₁  x₂  x₃  …  xₙ]]

means

[x₁  x₂  x₃  …  xₙ]
 ↓   ↓   ↓      ↓
[fx₁ fx₂ x₃  …  fxₙ]

There are not just two different ways of writing that for-loop -- upwards and downwards -- there are n! ways.

And even that assumes that each arrow is atomically and sequentially performed.

An assumption quite ok for a sequential machine completely unnecessary for a programmer.  Give up that assumption and the ways are infinite

IOW the second view is more abstract and programmer friendly than the first
in the same way that
saying the C expression "x+1"
"Adds 1 to the variable x"

rather than saying

"Its the C version of add 1, %eax"
[Why not inc %eax ?]

And this despite the fact that mathematical integers and real are rather far
removed from C's int and float.  IOW white lies are preferable to exact precise 
gobbledygook.

If the semantics of the comprehension depends on the order of the arrows,
the comprehension is screwed


Shorter technological answer:
In Haskell a side-effecting function gets a monadic type -- the type carries the
moniker "I am side-effecting" and so it cant be put in to a comprehension without type errors.

Now python's type system cannot do what Haskell's can [for better or worse is 
another matter -- a strong type system can be neat or a pain]

Considering that python's comprehensions are cloned from Haskell, it seems fair
that Haskell's formal strictures be passed on to beginners at least informally

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web