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


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

Comprehension with two variables - explanation needed

Started by"Ivan Evstegneev" <webmailgroups@gmail.com>
First post2014-11-23 16:56 +0200
Last post2014-11-23 17:46 +0000
Articles 17 — 9 participants

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


Contents

  Comprehension with two variables - explanation needed "Ivan Evstegneev" <webmailgroups@gmail.com> - 2014-11-23 16:56 +0200
    Re: Comprehension with two variables - explanation needed Rustom Mody <rustompmody@gmail.com> - 2014-11-23 07:09 -0800
      RE: Comprehension with two variables - explanation needed "Ivan Evstegneev" <webmailgroups@gmail.com> - 2014-11-23 17:37 +0200
      Re: Comprehension with two variables - explanation needed Chris Angelico <rosuav@gmail.com> - 2014-11-24 02:42 +1100
      RE: Comprehension with two variables - explanation needed Skip Montanaro <skip.montanaro@gmail.com> - 2014-11-23 09:45 -0600
        Re: Comprehension with two variables - explanation needed Roy Smith <roy@panix.com> - 2014-11-23 10:57 -0500
          Re: Comprehension with two variables - explanation needed Rustom Mody <rustompmody@gmail.com> - 2014-11-23 08:45 -0800
            Re: Comprehension with two variables - explanation needed Rustom Mody <rustompmody@gmail.com> - 2014-11-23 09:17 -0800
            RE: Comprehension with two variables - explanation needed "Ivan Evstegneev" <webmailgroups@gmail.com> - 2014-11-23 19:27 +0200
            Re: Comprehension with two variables - explanation needed Steven D'Aprano <steve@pearwood.info> - 2014-11-24 04:42 +0000
              Re: Comprehension with two variables - explanation needed Chris Angelico <rosuav@gmail.com> - 2014-11-24 15:51 +1100
                Re: Comprehension with two variables - explanation needed Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-11-25 09:20 +1100
              Re: Comprehension with two variables - explanation needed Rustom Mody <rustompmody@gmail.com> - 2014-11-23 22:47 -0800
              Re: Comprehension with two variables - explanation needed Dan Stromberg <drsalists@gmail.com> - 2014-11-24 16:42 -0800
          Re: Comprehension with two variables - explanation needed Skip Montanaro <skip.montanaro@gmail.com> - 2014-11-23 10:45 -0600
          Re: Comprehension with two variables - explanation needed Roy Smith <roy@panix.com> - 2014-11-23 12:08 -0500
          Re: Comprehension with two variables - explanation needed Jon Ribbens <jon+usenet@unequivocal.co.uk> - 2014-11-23 17:46 +0000

#81367 — Comprehension with two variables - explanation needed

From"Ivan Evstegneev" <webmailgroups@gmail.com>
Date2014-11-23 16:56 +0200
SubjectComprehension with two variables - explanation needed
Message-ID<mailman.16184.1416754678.18130.python-list@python.org>

[Multipart message — attachments visible in raw view] — view raw

Hello guys,

 

I would like to ask you for some explanations on comprehensions. (Don't be
scared, it just some particular example ^_^)

 

I found this little "find prime number" example over the internet:

 

>>> noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)]
>>> primes = [x for x in range(2, 50) if x not in noprimes]
>>> print primes


[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

 

 

It looked  pretty clear to me, till the time I decided to make some changes
to it %)))

 

Ok this is the case: 

 

As you can see the first line's comprehension produces a list, that includes
all the multiplications of "i" (that range(2,8) ) in range (i*2, 50, i).

So  I get this pattern: noprimes  = =  [4, 6, 8...48, 6, 9,12.. ].

The change that I tried to apply to this comprehension would lead to the
following pattern: noprimes = = [[4, 6,8.48], [6, 9, 12..], ..,[some
numbers]] 

 

But despite my struggling on it for the whole day, I haven't got to the
desirable result(using comprehensions only) 

 

Please, don't get me wrong, I'm not a lazy one (just a beginner). 

 

In my case, I  made some googling, and found some patterns for matrices,
that look this one(for example):

 

Matrix = [[0 for x in range(5)] for x in range(5)]

 

But when I tried to use square brackets with my code, it yields an error
about definition of "i", for instance:

 

File "<pyshell#30>", line 1, in <module>

noprimes = [[j for i in range(2, 8)] for j in range(i*2, 50, i)]

NameError: name 'i' is not defined.

 

Then I tried to apply those brackets to "j", like this: 

 

>>> noprimes = [[j] for i in range(2, 8) for j in range(i*2, 50, i)]

 

In this case I get, pretty predictable result, like this: [[num], [num],
[num],...,[num]], and  this is still not what I'm looking for..

 

So I moved further, and succeeded to solve my problem in a different manner:

 

>>> noprimes=[]

>>> for i in range(2,8):

noprimes.append(list(range(i*2,50,i)))

 

Which yields, in fact, the matrix I wanted from the beginning:

 

noprimes == [[4, 6, 8, 10, 12,.., 48], [6, 9, 12, 15, 18, ., 42, 45,
48],..,[numbers]]

Yep, this the "classical" way for me, on the other hand I have the feeling,
that this is not, the ultimate solution. ^_^

 

So my questions is still persists:

 

1)      Is it possible to realize such a thing by applying changes only to
initial comprehension? If yes, it would be nice to see the solution.

2)      How actually bad is my solution? I mean, after all, there are nested
functions call in my code,  so how much the speed is affected(if any)? 

 

Thanks a lot in advance,

 

Ivan.

[toc] | [next] | [standalone]


#81368

FromRustom Mody <rustompmody@gmail.com>
Date2014-11-23 07:09 -0800
Message-ID<d1194d28-e9ed-4bd3-86e9-899e13a17097@googlegroups.com>
In reply to#81367
On Sunday, November 23, 2014 8:28:16 PM UTC+5:30, Ivan Evstegneev wrote:
> Hello guys,
>  
> I would like to ask you for some explanations on comprehensions. (Don't be scared, it just some particular example ^_^)
>  
> I found this little "find prime number" example over the internet:
>  
> >>> noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)]
> >>> primes = [x for x in range(2, 50) if x not in noprimes]
> >>> print primes
> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
>  
>  
> It looked  pretty clear to me, till the time I decided to make some changes to it %)))
>  
> Ok this is the case: 
>  
> As you can see the first line's comprehension produces a list, that includes all the multiplications of "i" (that range(2,8) ) in range (i*2, 50, i).
> So  I get this pattern: noprimes  = =  [4, 6, 8.....48, 6, 9,12.... ].
> The change that I tried to apply to this comprehension would lead to the following pattern: noprimes = = [[4, 6,8...48], [6, 9, 12....], ....,[some numbers]] 
>  
> But despite my struggling on it for the whole day, I haven't got to the desirable result(using comprehensions only) 
>  
> Please, don't get me wrong, I'm not a lazy one (just a beginner). 
>  
> In my case, I  made some googling, and found some patterns for matrices, that look this one(for example):
>  
> Matrix = [[0 for x in range(5)] for x in range(5)]
>  
> But when I tried to use square brackets with my code, it yields an error about definition of "i", for instance:
>  
> File "<pyshell#30>", line 1, in <module>
> noprimes = [[j for i in range(2, 8)] for j in range(i*2, 50, i)]
> NameError: name 'i' is not defined.

Is this what you want?

>>> [[j for j in range(i*2, 50, i)] for i in range(2,8)]
[[4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48], [6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48], [8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48], [10, 15, 20, 25, 30, 35, 40, 45], [12, 18, 24, 30, 36, 42, 48], [14, 21, 28, 35, 42, 49]]

[I am not sure what you are trying -- just making local
changes to the ZF to make it work]

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


#81374

From"Ivan Evstegneev" <webmailgroups@gmail.com>
Date2014-11-23 17:37 +0200
Message-ID<mailman.16188.1416757120.18130.python-list@python.org>
In reply to#81368
>Is this what you want?
>
>>>> [[j for j in range(i*2, 50, i)] for i in range(2,8)]
>[[4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40,
42, 44, 46, 48], [6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48],
[8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48], [10, >15, 20, 25, 30, 35, 40,
45], [12, 18, 24, 30, 36, 42, 48], [14, 21, 28, 35, 42, 49]]

>[I am not sure what you are trying -- just making local changes to the ZF
to make it work]

>https://mail.python.org/mailman/listinfo/python-list

Yes, awesome. Thanks.

But it breaks all the picture that I've built in my head about comps till
now...

As I know from books and googling, the comps main idea looks approximately
like this:

[target <--main loop<--nested loop/s (and maybe some conditions)]    Am I
right? 

But your code looks somehow inverted to me o_0

Like: 

[[target with nested  loop] <--- main loop with initial values for target]

On the other hand, if I'm comparing to my tryouts:

noprimes = [[j for i in range(2, 8)] for j in range(i*2, 50, i)]

It looks same but the variables are not separated, so it definitely  was not
defined....

Sincerely,

Ivan


     




-----Original Message-----
From: Python-list
[mailto:python-list-bounces+webmailgroups=gmail.com@python.org] On Behalf Of
Rustom Mody
Sent: Sunday, November 23, 2014 17:09
To: python-list@python.org
Subject: Re: Comprehension with two variables - explanation needed

On Sunday, November 23, 2014 8:28:16 PM UTC+5:30, Ivan Evstegneev wrote:
> Hello guys,
>  
> I would like to ask you for some explanations on comprehensions. 
> (Don't be scared, it just some particular example ^_^)
>  
> I found this little "find prime number" example over the internet:
>  
> >>> noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)] 
> >>> primes = [x for x in range(2, 50) if x not in noprimes] print 
> >>> primes
> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
>  
>  
> It looked  pretty clear to me, till the time I decided to make some 
> changes to it %)))
>  
> Ok this is the case: 
>  
> As you can see the first line's comprehension produces a list, that
includes all the multiplications of "i" (that range(2,8) ) in range (i*2,
50, i).
> So  I get this pattern: noprimes  = =  [4, 6, 8.....48, 6, 9,12.... ].
> The change that I tried to apply to this comprehension would lead to 
> the following pattern: noprimes = = [[4, 6,8...48], [6, 9, 12....], 
> ....,[some numbers]]
>  
> But despite my struggling on it for the whole day, I haven't got to 
> the desirable result(using comprehensions only)
>  
> Please, don't get me wrong, I'm not a lazy one (just a beginner). 
>  
> In my case, I  made some googling, and found some patterns for matrices,
that look this one(for example):
>  
> Matrix = [[0 for x in range(5)] for x in range(5)]
>  
> But when I tried to use square brackets with my code, it yields an error
about definition of "i", for instance:
>  
> File "<pyshell#30>", line 1, in <module> noprimes = [[j for i in 
> range(2, 8)] for j in range(i*2, 50, i)]
> NameError: name 'i' is not defined.

Is this what you want?

>>> [[j for j in range(i*2, 50, i)] for i in range(2,8)]
[[4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40,
42, 44, 46, 48], [6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48],
[8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48], [10, 15, 20, 25, 30, 35, 40,
45], [12, 18, 24, 30, 36, 42, 48], [14, 21, 28, 35, 42, 49]]

[I am not sure what you are trying -- just making local changes to the ZF to
make it work]
--
https://mail.python.org/mailman/listinfo/python-list

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


#81376

FromChris Angelico <rosuav@gmail.com>
Date2014-11-24 02:42 +1100
Message-ID<mailman.16189.1416757339.18130.python-list@python.org>
In reply to#81368
On Mon, Nov 24, 2014 at 2:37 AM, Ivan Evstegneev
<webmailgroups@gmail.com> wrote:
> As I know from books and googling, the comps main idea looks approximately
> like this:
>
> [target <--main loop<--nested loop/s (and maybe some conditions)]    Am I
> right?
>
> But your code looks somehow inverted to me o_0
>
> Like:
>
> [[target with nested  loop] <--- main loop with initial values for target]

Your analysis is correct, and it's because of the bracketing. Just as
you learned back in maths class (or math class, if you're that sort),
you start from the innermost brackets and work your way out. In fact,
the nested example starts with the main loop, and for each value it
goes through, it creates the entire inner comprehension.

ChrisA

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


#81378

FromSkip Montanaro <skip.montanaro@gmail.com>
Date2014-11-23 09:45 -0600
Message-ID<mailman.16191.1416757555.18130.python-list@python.org>
In reply to#81368

[Multipart message — attachments visible in raw view] — view raw

> But it breaks all the picture that I've built in my head about comps till
> now...

Note that list comprehensions are little more than syntactic sugar for for
loops. If you're having terrible writing or understanding one, especially a
compound one like your example, it can help to write it as a (nested) for
loop, then covert it (perhaps incrementally) to the list comp form.

Skip

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


#81380

FromRoy Smith <roy@panix.com>
Date2014-11-23 10:57 -0500
Message-ID<roy-B11F64.10563923112014@news.panix.com>
In reply to#81378
In article <mailman.16191.1416757555.18130.python-list@python.org>,
 Skip Montanaro <skip.montanaro@gmail.com> wrote:

> > But it breaks all the picture that I've built in my head about comps till
> > now...
> 
> Note that list comprehensions are little more than syntactic sugar for for
> loops. If you're having terrible writing or understanding one, especially a
> compound one like your example, it can help to write it as a (nested) for
> loop, then covert it (perhaps incrementally) to the list comp form.

Or not.  If it was complicated enough that you needed to loopify it to 
understand what it's doing, have pity on the next person who has to 
maintain your code and leave it as a loop :-)

My general rule for code hygiene is, "If I have to think about whether 
something is too complicated, it is".

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


#81386

FromRustom Mody <rustompmody@gmail.com>
Date2014-11-23 08:45 -0800
Message-ID<07f25264-1286-4d98-820c-949dba711248@googlegroups.com>
In reply to#81380
On Sunday, November 23, 2014 9:27:22 PM UTC+5:30, Roy Smith wrote:
>  Skip Montanaro wrote:
> 
> > > But it breaks all the picture that I've built in my head about comps till
> > > now...
> > 
> > Note that list comprehensions are little more than syntactic sugar for for
> > loops. If you're having terrible writing or understanding one, especially a
> > compound one like your example, it can help to write it as a (nested) for
> > loop, then covert it (perhaps incrementally) to the list comp form.
> 
> Or not.  If it was complicated enough that you needed to loopify it to 
> understand what it's doing, have pity on the next person who has to 
> maintain your code and leave it as a loop :-)
> 
> My general rule for code hygiene is, "If I have to think about whether 
> something is too complicated, it is".

[I guess I am in the minority here... anyways... here goes]

1. I find comprehensions are harder than for-loops -- corollary to
functional code is easier than imperative --
corollary to time is a major headache. If the problem does not
involve time the solution should try to avoid it

2. "List comprehensions are syntactic sugar for for loops"
Cannot technically quarrel with that as that is the position of the official
docs.
However to me it puts the cart before the horse.
Its like saying that 

def foo(x): return x+1

is just the same as

              0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 (1)
              6 BINARY_ADD
              7 RETURN_VALUE


(output of dis)

That may be the case but it seems (to me at least) to defeat the purpose
of using an hi-level language.

3. So how should one think of list comprehensions?
   As a python/executable version of 'set-builder notation'
   http://en.wikipedia.org/wiki/Set-builder_notation

4. Finally to the OP (assuming you wanted a prime-number generator)
Heres a solution for your consideration.

First a one-line solution in haskell

sieve (p:xs)   =    p:sieve [x | x <- xs, x `mod` p /= 0]

Call with sieve [2..]

Now a pythonification of that

def n2s():  # natural nos from 2; ie [2..]
    i=2
    while True:
        yield i
        i+=1

def sieve(l):
    p = next(l)
    yield p
    yield from sieve (x for x in l if x % p != 0)


Call as
for p in sieve(n2s()): print(p)

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


#81393

FromRustom Mody <rustompmody@gmail.com>
Date2014-11-23 09:17 -0800
Message-ID<40dd9920-ec78-4ebe-865a-e9f7c9c9a7d1@googlegroups.com>
In reply to#81386
On Sunday, November 23, 2014 10:15:51 PM UTC+5:30, Rustom Mody wrote:
> 1. I find comprehensions are harder than for-loops -- 

Heh! Meant to say 'easier' of course...

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


#81394

From"Ivan Evstegneev" <webmailgroups@gmail.com>
Date2014-11-23 19:27 +0200
Message-ID<mailman.16201.1416764650.18130.python-list@python.org>
In reply to#81386
Got the main idea. 
Still need to "chew it up"  in depth. (As I mentioned I'm a beginner.... EE
student, so please excuse me for my  "lameness"  ^_^)

-----Original Message-----
From: Python-list
[mailto:python-list-bounces+webmailgroups=gmail.com@python.org] On Behalf Of
Rustom Mody
Sent: Sunday, November 23, 2014 18:46
To: python-list@python.org
Subject: Re: Comprehension with two variables - explanation needed

On Sunday, November 23, 2014 9:27:22 PM UTC+5:30, Roy Smith wrote:
>  Skip Montanaro wrote:
> 
> > > But it breaks all the picture that I've built in my head about 
> > > comps till now...
> > 
> > Note that list comprehensions are little more than syntactic sugar 
> > for for loops. If you're having terrible writing or understanding 
> > one, especially a compound one like your example, it can help to 
> > write it as a (nested) for loop, then covert it (perhaps incrementally)
to the list comp form.
> 
> Or not.  If it was complicated enough that you needed to loopify it to 
> understand what it's doing, have pity on the next person who has to 
> maintain your code and leave it as a loop :-)
> 
> My general rule for code hygiene is, "If I have to think about whether 
> something is too complicated, it is".

[I guess I am in the minority here... anyways... here goes]

1. I find comprehensions are harder than for-loops -- corollary to
functional code is easier than imperative -- corollary to time is a major
headache. If the problem does not involve time the solution should try to
avoid it

2. "List comprehensions are syntactic sugar for for loops"
Cannot technically quarrel with that as that is the position of the official
docs.
However to me it puts the cart before the horse.
Its like saying that 

def foo(x): return x+1

is just the same as

              0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 (1)
              6 BINARY_ADD
              7 RETURN_VALUE


(output of dis)

That may be the case but it seems (to me at least) to defeat the purpose of
using an hi-level language.

3. So how should one think of list comprehensions?
   As a python/executable version of 'set-builder notation'
   http://en.wikipedia.org/wiki/Set-builder_notation

4. Finally to the OP (assuming you wanted a prime-number generator) Heres a
solution for your consideration.

First a one-line solution in haskell

sieve (p:xs)   =    p:sieve [x | x <- xs, x `mod` p /= 0]

Call with sieve [2..]

Now a pythonification of that

def n2s():  # natural nos from 2; ie [2..]
    i=2
    while True:
        yield i
        i+=1

def sieve(l):
    p = next(l)
    yield p
    yield from sieve (x for x in l if x % p != 0)


Call as
for p in sieve(n2s()): print(p)
--
https://mail.python.org/mailman/listinfo/python-list

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


#81423

FromSteven D'Aprano <steve@pearwood.info>
Date2014-11-24 04:42 +0000
Message-ID<5472b74d$0$12979$c3e8da3$5496439d@news.astraweb.com>
In reply to#81386
On Sun, 23 Nov 2014 08:45:39 -0800, Rustom Mody wrote:

> 2. "List comprehensions are syntactic sugar for for loops" Cannot
> technically quarrel with that as that is the position of the official
> docs.
> However to me it puts the cart before the horse. Its like saying that
> 
> def foo(x): return x+1
> 
> is just the same as
> 
>               0 LOAD_FAST                0 (x)
>               3 LOAD_CONST               1 (1)
>               6 BINARY_ADD
>               7 RETURN_VALUE
> 
> 
> (output of dis)


The two situations are not related. The output of dis is an 
implementation detail. Try running it under IronPython or Jython and see 
what you get. Even in CPython, it is still an implementation detail 
subject to change. Today dis() returns the above, tomorrow it may return:

              0 LOAD_GLOBAL              0 (x)
              3 INCREMENT
              5 RETURN_VALUE

(say), and the Python code remains the same even though the byte code is 
different.

Whereas the statement that "comprehensions are syntactic sugar for for-
loops" is a statement about the semantics of comprehensions. It's a 
language promise, part of the API of Python, and not subject to change 
without a period of deprecation.  It is a promise that

    [expression for name in sequence]

is closely equivalent to:

    for name in sequence:
        expression


(They are not *identical* because list comprehensions collect the result 
of expression into a list, set comprehensions collect them into a set, 
etc. But the actual looping part is the same.)


> 3. So how should one think of list comprehensions?
>    As a python/executable version of 'set-builder notation'
>    http://en.wikipedia.org/wiki/Set-builder_notation

For those who learned, and remember, set-builder notation, that is an 
excellent analogy.


> 4. Finally to the OP (assuming you wanted a prime-number generator)
> Heres a solution for your consideration.
> 
> First a one-line solution in haskell
> 
> sieve (p:xs)   =    p:sieve [x | x <- xs, x `mod` p /= 0]

Don't use that! That is a horribly inefficient way to generate primes.

Mathematically, it is a version of Euler's Sieve. It is sometimes wrongly 
described as "Sieve of Eratosthenes", but that is wrong. Due to it's 
horrible performance, Melissa O'Neill calls this the "Sleight on 
Eratosthenes":

http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

Asymptotic behaviour of this is O(N**2/(log N)**2) which is worse than 
trial division and only *marginally* better than this stupidly naive 
version:

def primes0():
    i = 2
    yield i
    while True:
        i += 1
        composite = False
        for p in range(2, i):
            if i%p == 0:
                composite = True
        if not composite:  # It must be a prime.
            yield i



> Call with sieve [2..]
> 
> Now a pythonification of that
[...]





-- 
Steven

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


#81426

FromChris Angelico <rosuav@gmail.com>
Date2014-11-24 15:51 +1100
Message-ID<mailman.16222.1416804702.18130.python-list@python.org>
In reply to#81423
On Mon, Nov 24, 2014 at 3:42 PM, Steven D'Aprano <steve@pearwood.info> wrote:
> Today dis() returns the above, tomorrow it may return:
>
>               0 LOAD_GLOBAL              0 (x)
>               3 INCREMENT
>               5 RETURN_VALUE
>
> (say), and the Python code remains the same even though the byte code is
> different.

I hope not! The x in the original function was a local, not a global,
and if dis.dis() says LOAD_GLOBAL for something that's not global, it
would be *very* confusing! :)

But yes, CPython could grow an INCREMENT bytecode, and it'd not break anything.

ChrisA

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


#81471

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2014-11-25 09:20 +1100
Message-ID<5473af18$0$13004$c3e8da3$5496439d@news.astraweb.com>
In reply to#81426
Chris Angelico wrote:

> On Mon, Nov 24, 2014 at 3:42 PM, Steven D'Aprano <steve@pearwood.info>
> wrote:
>> Today dis() returns the above, tomorrow it may return:
>>
>>               0 LOAD_GLOBAL              0 (x)
>>               3 INCREMENT
>>               5 RETURN_VALUE
>>
>> (say), and the Python code remains the same even though the byte code is
>> different.
> 
> I hope not! The x in the original function was a local, not a global,

D'oh!

I mean, yes, that was a test to see if you were paying attention, and you
have passed! Well done.

*whistles nonchalantly*


-- 
Steven

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


#81436

FromRustom Mody <rustompmody@gmail.com>
Date2014-11-23 22:47 -0800
Message-ID<24e2bcc9-9b48-4f7b-a8aa-a7ad8a7051d1@googlegroups.com>
In reply to#81423
On Monday, November 24, 2014 10:13:04 AM UTC+5:30, Steven D'Aprano wrote:
> On Sun, 23 Nov 2014 08:45:39 -0800, Rustom Mody wrote:
> > First a one-line solution in haskell
> > 
> > sieve (p:xs)   =    p:sieve [x | x <- xs, x `mod` p /= 0]
> 
> Don't use that! That is a horribly inefficient way to generate primes.
> 
> Mathematically, it is a version of Euler's Sieve. It is sometimes wrongly 
> described as "Sieve of Eratosthenes", but that is wrong. Due to it's 
> horrible performance, Melissa O'Neill calls this the "Sleight on 
> Eratosthenes":
> 
> http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

Thanks for that link -- I'll need to look at it carefully

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


#81477

FromDan Stromberg <drsalists@gmail.com>
Date2014-11-24 16:42 -0800
Message-ID<mailman.16260.1416876136.18130.python-list@python.org>
In reply to#81423
On Sun, Nov 23, 2014 at 8:42 PM, Steven D'Aprano <steve@pearwood.info> wrote:
> On Sun, 23 Nov 2014 08:45:39 -0800, Rustom Mody wrote:
>> First a one-line solution in haskell
>>
>> sieve (p:xs)   =    p:sieve [x | x <- xs, x `mod` p /= 0]
>
> Don't use that! That is a horribly inefficient way to generate primes.
>
> Mathematically, it is a version of Euler's Sieve. It is sometimes wrongly
> described as "Sieve of Eratosthenes", but that is wrong. Due to it's
> horrible performance, Melissa O'Neill calls this the "Sleight on
> Eratosthenes":

I don't read Haskell, but here's a Sieve (or at least I thought it was
a Sieve) and a few other prime-related things:
http://stromberg.dnsalias.org/~dstromberg/primes/

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


#81387

FromSkip Montanaro <skip.montanaro@gmail.com>
Date2014-11-23 10:45 -0600
Message-ID<mailman.16197.1416761116.18130.python-list@python.org>
In reply to#81380
On Sun, Nov 23, 2014 at 9:57 AM, Roy Smith <roy@panix.com> wrote:
>
> If it was complicated enough that you needed to loopify it to
> understand what it's doing, have pity on the next person who has to
> maintain your code and leave it as a loop

Well, sure. I was mostly trying to give Ivan a path out of the weeds.
Poking through the code I'm involved with at work, using a crude
measuring stick (a couple regular expressions) I found over 1400 one
line list comprehensions, those which matched this regular expression:

\[.* for .*\]

OTOH, I only found 14 with two "for" keywords:

\[.* for .* for .*\]

(There may well have been more nested loop list comprehensions, simply
because it's hard to cram the full listcomp into 80 columns, my
self-imposed column limit.)

In my experience, list comprehensions rapidly get unwieldy once you
get to nesting them. I generally unravel such items into a nested set
of for loops.

Skip

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


#81392

FromRoy Smith <roy@panix.com>
Date2014-11-23 12:08 -0500
Message-ID<mailman.16200.1416762503.18130.python-list@python.org>
In reply to#81380
We seem to be somewhat more liberal about nested comprehensions here, but I can't say I'm proud of that :-)

906 Python source files, 109k lines. 

$ find . -name '*.py' | xargs grep '\[.* for .*\]' | wc -l
729

$ find . -name '*.py' | xargs grep '\[.* for .* for .*\]' | wc -l
46

Without naming names, a quick look into our nested comprehensions with "hg blame" shows a very strong correlation between "people who wrote many nested comprehensions" and "people who's code I find difficult to read in general".  I see one of these that has my name on the commit:

   report = [keys] + [[line[key] for key in keys] for line in results]

but I'm glad to report that this was merely some third-party code that I imported into our repo.  Whew, that was close!

On Nov 23, 2014, at 11:45 AM, Skip Montanaro wrote:

> On Sun, Nov 23, 2014 at 9:57 AM, Roy Smith <roy@panix.com> wrote:
>> 
>> If it was complicated enough that you needed to loopify it to
>> understand what it's doing, have pity on the next person who has to
>> maintain your code and leave it as a loop
> 
> Well, sure. I was mostly trying to give Ivan a path out of the weeds.
> Poking through the code I'm involved with at work, using a crude
> measuring stick (a couple regular expressions) I found over 1400 one
> line list comprehensions, those which matched this regular expression:
> 
> \[.* for .*\]
> 
> OTOH, I only found 14 with two "for" keywords:
> 
> \[.* for .* for .*\]
> 
> (There may well have been more nested loop list comprehensions, simply
> because it's hard to cram the full listcomp into 80 columns, my
> self-imposed column limit.)
> 
> In my experience, list comprehensions rapidly get unwieldy once you
> get to nesting them. I generally unravel such items into a nested set
> of for loops.
> 
> Skip
> 


--
Roy Smith
roy@panix.com


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


#81395

FromJon Ribbens <jon+usenet@unequivocal.co.uk>
Date2014-11-23 17:46 +0000
Message-ID<slrnm747bp.jls.jon+usenet@frosty.unequivocal.co.uk>
In reply to#81380
On 2014-11-23, Roy Smith <roy@panix.com> wrote:
> In article <mailman.16191.1416757555.18130.python-list@python.org>,
>  Skip Montanaro <skip.montanaro@gmail.com> wrote:
>> > But it breaks all the picture that I've built in my head about comps till
>> > now...
>> 
>> Note that list comprehensions are little more than syntactic sugar for for
>> loops. If you're having terrible writing or understanding one, especially a
>> compound one like your example, it can help to write it as a (nested) for
>> loop, then covert it (perhaps incrementally) to the list comp form.
>
> Or not.  If it was complicated enough that you needed to loopify it to 
> understand what it's doing, have pity on the next person who has to 
> maintain your code and leave it as a loop :-)
>
> My general rule for code hygiene is, "If I have to think about whether 
> something is too complicated, it is".

My reminder rule for nested comprehensions is "Which way do you
instinctively think they should nest and makes logical sense?
They don't work that way."

[toc] | [prev] | [standalone]


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


csiph-web