Path: csiph.com!usenet.pasdenom.info!weretis.net!feeder1.news.weretis.net!feeder.erje.net!eu.feeder.erje.net!newsfeed.xs4all.nl!newsfeed4a.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; '16,': 0.03; 'algorithm': 0.04; 'patterns': 0.04; 'skip:[ 20': 0.04; 'explicitly': 0.05; 'root': 0.05; '21,': 0.07; 'explicit': 0.07; 'nested': 0.07; 'subject:two': 0.07; '22,': 0.09; '34,': 0.09; '40,': 0.09; 'calls.': 0.09; 'executed': 0.09; 'function,': 0.09; 'internet:': 0.09; 'level:': 0.09; 'list).': 0.09; 'tmp': 0.09; 'wrong,': 0.09; 'translate': 0.10; 'cc:addr:python-list': 0.11; 'python': 0.11; 'changes': 0.15; '(just': 0.16; '23,': 0.16; '24,': 0.16; '32,': 0.16; '33,': 0.16; '36,': 0.16; '37,': 0.16; '39,': 0.16; '42,': 0.16; '46,': 0.16; '50)': 0.16; '[2,': 0.16; 'any)?': 0.16; 'brackets': 0.16; 'comp': 0.16; 'deduced': 0.16; 'defined.': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'guys,': 0.16; 'instance:': 0.16; 'iteration': 0.16; 'iterator': 0.16; 'itself,': 0.16; 'ivan': 0.16; 'i\xe2\x80\x99m': 0.16; 'loops': 0.16; 'mean,': 0.16; 'nameerror:': 0.16; 'nesting': 0.16; 'once;': 0.16; 'only)': 0.16; 'utterly': 0.16; 'wrote:': 0.18; 'variable': 0.18; 'all,': 0.19; 'not,': 0.20; 'solution.': 0.20; '(the': 0.22; '>>>': 0.22; 'code,': 0.22; 'example': 0.22; 'cc:addr:python.org': 0.22; 'print': 0.22; 'error': 0.23; '31,': 0.24; 'stopping': 0.24; 'fairly': 0.24; 'initial': 0.24; 'mon,': 0.24; 'cc:2**0': 0.24; '15,': 0.26; 'first,': 0.26; 'this:': 0.26; 'header:In-Reply-To:1': 0.27; 'tried': 0.27; 'function': 0.29; 'leave': 0.29; 'am,': 0.29; "doesn't": 0.30; 'list:': 0.30; 'moved': 0.30; 'message-id:@mail.gmail.com': 0.30; '"",': 0.31; '13,': 0.31; '25,': 0.31; '50,': 0.31; 'minor': 0.31; 'yields': 0.31; 'file': 0.32; 'lists': 0.32; 'there.': 0.32; "we're": 0.32; 'another': 0.32; 'quite': 0.32; 'running': 0.33; 'problem': 0.35; 'subject:with': 0.35; "can't": 0.35; 'created': 0.35; 'case,': 0.35; 'definition': 0.35; 'but': 0.35; 'received:google.com': 0.35; 'there': 0.35; '14,': 0.36; 'possible': 0.36; 'so,': 0.37; 'list': 0.37; 'easily': 0.37; 'performance': 0.37; 'starting': 0.37; 'nov': 0.38; 'subject:needed': 0.38; 'back': 0.62; 'name': 0.63; 'such': 0.63; 'skip:n 10': 0.64; 'more': 0.64; 'different': 0.65; '30,': 0.65; 'skip:\xe2 10': 0.65; 'details': 0.65; 'here': 0.66; '20,': 0.68; '26,': 0.68; '8bit%:40': 0.68; 'fact,': 0.69; 'applying': 0.72; 'further,': 0.74; 'prime': 0.74; 'square': 0.74; 'walk': 0.74; 'increase': 0.74; 'hand': 0.80; 'counts': 0.83; '^_^': 0.84; 'here)': 0.84; 'leak': 0.84; 'composite': 0.91; 'don\xe2\x80\x99t': 0.91; 'lazy': 0.91; 'to:none': 0.92; 'differences': 0.93; 'ultimate': 0.93 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:cc :content-type:content-transfer-encoding; bh=K+TFX6zFeArNCXTpiYE0pMIToPo6J+OkAxpnMU4TIMo=; b=jpO49b0NRx2sjWDMAwZ1BCQyMOihHo1bnTGiql17oJLiJmHbhn8t2WOaHFjV6K9YCW RRF59GEzjLffS1XQigI9+Wdfk31GNVBszGbDCbWEkUMW51Jq9Fr+aENqMhiNFGGel0R1 weeXqnFfBH8sbtr0PRj7J2oM/GbB8CWvJ0DxQgNTQ4JN9l3WXXGo15pHhOtq0vbdfmzR GlFREL0eEmxrh3H3JTUl+eaqN/WeZhR8Wtl7G6I4ZCKRNZFO6y0mR62WlMyPsi6LcDn1 DZS0OuillgIVJ7WXA0o/K4jLOzuJqjzRO0upcUmvoEjQCjc4UzPicqe/O1lsW4nAm6vY sn6g== MIME-Version: 1.0 X-Received: by 10.107.134.39 with SMTP id i39mr13682664iod.53.1416756095456; Sun, 23 Nov 2014 07:21:35 -0800 (PST) In-Reply-To: <002001d0072d$b9b5da50$2d218ef0$@gmail.com> References: <002001d0072d$b9b5da50$2d218ef0$@gmail.com> Date: Mon, 24 Nov 2014 02:21:35 +1100 Subject: Re: Comprehension with two variables - explanation needed From: Chris Angelico Cc: "python-list@python.org" Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 130 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1416756098 news.xs4all.nl 2849 [2001:888:2000:d::a6]:34466 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:81370 On Mon, Nov 24, 2014 at 1:56 AM, Ivan Evstegneev wrote: > > Hello guys, > > I would like to ask you for some explanations on comprehensions. (Don=E2= =80=99t be scared, it just some particular example ^_^) > > I found this little =E2=80=9Cfind prime number=E2=80=9D example over the = internet: > > >>> noprimes =3D [j for i in range(2, 8) for j in range(i*2, 50, i)] > >>> primes =3D [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] Okay, this is a pretty ham-fisted way of enumerating prime numbers, but let me walk you through it. First, let's look at the composite numbers (the 'noprimes' list). That comprehension is identical (apart from some details that don't matter here) to this: noprimes =3D [] for i in range(2,8): for j in range(i*2, 50, i): noprimes.append(j) So, as you correctly deduced below, what you have is this list: [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] The inner loop (with j as its iteration variable) counts up in increments of i, starting at twice i, stopping once it's gone past fifty. That means it's every multiple of i other than i itself, which means these are by definition composite numbers. Note that quite a few of the numbers are coming up more than once; this would be more efficient as a set comprehension, but leave that aside for now. Note also that the range for i has to go as far as the square root of the number we're working with - we have to go as far as 7*7=3D=3D49. If you want primes to some higher cap, say 100, you'd need to also increase that, eg range(2,11). > The change that I tried to apply to this comprehension would lead to the = following pattern: noprimes =3D =3D [[4, 6,8=E2=80=A648], [6, 9, 12=E2=80= =A6.], =E2=80=A6.,[some numbers]] > > But despite my struggling on it for the whole day, I haven=E2=80=99t got = to the desirable result(using comprehensions only) > > Please, don=E2=80=99t get me wrong, I=E2=80=99m not a lazy one (just a be= ginner). > > In my case, I made some googling, and found some patterns for matrices, = that look this one(for example): > > Matrix =3D [[0 for x in range(5)] for x in range(5)] The inner lists there can be created more simply, since you're working with integers: [[0]*5 for x in range(5)] > But when I tried to use square brackets with my code, it yields an error = about definition of =E2=80=9Ci=E2=80=9D, for instance: > > File "", line 1, in > > noprimes =3D [[j for i in range(2, 8)] for j in range(i*2, 50, i)] > > NameError: name 'i' is not defined. That's because you have your nesting backwards. Instead of having the for loops running left-to-right, they now are explicitly bracketed to be the other way around. This is more like: noprimes =3D [] for j in range(i*2, 50, i): noprimes.append([j for i in range(2, 8)]) which can be unrolled another level: noprimes =3D [] for j in range(i*2, 50, i): tmp =3D [] for i in range(2, 8): tmp.append(j) noprimes.append(tmp) Now you can see why i doesn't exist there. > So I moved further, and succeeded to solve my problem in a different mann= er: > >>> noprimes=3D[] > > >>> 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: > > Yep, this the =E2=80=9Cclassical=E2=80=9D way for me, on the other hand I= have the feeling, that this is not, the ultimate solution. ^_^ In fact, this is exactly right, and now you can easily translate that back to list comp syntax: noprimes =3D [list(range(i*2,50,i)) for i in range(2,8)] > So my questions is still persists: > > 1) Is it possible to realize such a thing by applying changes only t= o 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 nes= ted functions call in my code, so how much the speed is affected(if any)? Don't worry about speed of function calls. The algorithm used here is so utterly appalling that it's going to get in your way long before the performance of Python will. :) List comprehensions are fairly readily convertible to and from explicit loops. There are a couple of minor differences (a list comp is actually executed inside a nested function, so the loop iterator variable can't leak out), but generally, if you're having trouble, just unroll the comprehension into a loop and see if it makes more sense. ChrisA