Re: [Tutor] "Strange" behaviour of list comprehension
On Wed, Feb 13, 2013 at 10:07 PM, Mahadevan, Anand wrote: > Thanks for the good explanation, Hugo. Not sure of the protocol for > replying in this forum, when I clicked on reply it filled your id in. > Glad I could be of help :) For future reference, it's generally considered politest to send all replies over the tutor mailing list as well so we can all see them, especially if further discussion is possible. Either click "Reply All" or make sure you have tutor@python.org in your CC list. Hugo ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] "Strange" behaviour of list comprehension
On Wed, Feb 13, 2013 at 9:17 AM, Hugo Arts wrote: > To be more precise, the comma at the end is part of a tuple (you can omit > parentheses of a tuple in many cases). This makes the final for loop iterate > over the tuple (range(y, 10), x + y == z). You'll notice that this only > works if the variable 'z' is already defined, since the tuple isn't > constructed in the for loop. In 3.x the parser requires the parentheses in a list comprehension, but not in a for loop. And the list comprehension is compiled as a function, so you get an UnboundLocalError when trying to evaluate x+y==z. Just for fun, here's an example that makes a function from the code of a list comprehension in 3.x. The function takes the first iterator in the comprehension as an argument: >>> f = lambda: [(x,y) for x in 'ab' for y in 'cd'] >>> lcomp = type(f)(f.__code__.co_consts[1], globals()) >>> lcomp(iter('12')) [('1', 'c'), ('1', 'd'), ('2', 'c'), ('2', 'd')] Never do this. The code assumes the argument is an iterator, so it's easy to trigger a segfault: >>> lcomp('12') Segmentation fault ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] "Strange" behaviour of list comprehension
On 13/02/2013 14:17, Hugo Arts wrote: To be more precise, the comma at the end is part of a tuple (you can omit parentheses of a tuple in many cases). Parantheses are not part of a tuple except in special cases, see http://docs.python.org/2/tutorial/datastructures.html#tuples-and-sequences -- Cheers. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] "Strange" behaviour of list comprehension
On Wed, Feb 13, 2013 at 2:45 PM, Mahadevan, Anand wrote: > I'm playing around with list comprehension and in IDLE typed this in. I > actually wanted it to return all tuples satisfying the condition where z is > the sum of x and y. I kind of got mixed up with the syntax, hence I put a > comma in there instead of an "if". I'd like some assistance understanding > what it's doing... > Thanks! > > >>> somelist = [(x,y,z) for x in range(1,10) for y in range(x,10) for z in > range(y,10), x+y==z] > >>> somelist > [(1, 1, [1, 2, 3, 4, 5, 6, 7, 8, 9]), (1, 1, False), (1, 2, [2, 3, 4, 5, > 6, 7, 8, 9]), (1, 2, False), (1, 3, [3, 4, 5, 6, 7, 8, 9]), (1, 3, False), > (1, 4, [4, 5, 6, 7, 8, 9]), (1, 4, False), (1, 5, [5, 6, 7, 8, 9]), (1, 5, > False), (1, 6, [6, 7, 8, 9]), (1, 6, False), (1, 7, [7, 8, 9]), (1, 7, > False), (1, 8, [8, 9]), (1, 8, False), (1, 9, [9]), (1, 9, False), (2, 2, > [2, 3, 4, 5, 6, 7, 8, 9]), (2, 2, False), (2, 3, [3, 4, 5, 6, 7, 8, 9]), > (2, 3, False), (2, 4, [4, 5, 6, 7, 8, 9]), (2, 4, False), (2, 5, [5, 6, 7, > 8, 9]), (2, 5, False), (2, 6, [6, 7, 8, 9]), (2, 6, False), (2, 7, [7, 8, > 9]), (2, 7, False), (2, 8, [8, 9]), (2, 8, False), (2, 9, [9]), (2, 9, > False), (3, 3, [3, 4, 5, 6, 7, 8, 9]), (3, 3, False), (3, 4, [4, 5, 6, 7, > 8, 9]), (3, 4, False), (3, 5, [5, 6, 7, 8, 9]), (3, 5, False), (3, 6, [6, > 7, 8, 9]), (3, 6, False), (3, 7, [7, 8, 9]), (3, 7, False), (3, 8, [8, 9]), > (3, 8, False), (3, 9, [9]), (3, 9, False), (4, 4, [4, 5, 6, 7, 8, 9]), (4, > 4, False), (4, 5, [5, 6, 7, 8, 9]), (4 > , 5, False), (4, 6, [6, 7, 8, 9]), (4, 6, False), (4, 7, [7, 8, 9]), (4, > 7, False), (4, 8, [8, 9]), (4, 8, False), (4, 9, [9]), (4, 9, False), (5, > 5, [5, 6, 7, 8, 9]), (5, 5, False), (5, 6, [6, 7, 8, 9]), (5, 6, False), > (5, 7, [7, 8, 9]), (5, 7, False), (5, 8, [8, 9]), (5, 8, False), (5, 9, > [9]), (5, 9, False), (6, 6, [6, 7, 8, 9]), (6, 6, False), (6, 7, [7, 8, > 9]), (6, 7, False), (6, 8, [8, 9]), (6, 8, False), (6, 9, [9]), (6, 9, > False), (7, 7, [7, 8, 9]), (7, 7, False), (7, 8, [8, 9]), (7, 8, False), > (7, 9, [9]), (7, 9, False), (8, 8, [8, 9]), (8, 8, False), (8, 9, [9]), (8, > 9, False), (9, 9, [9]), (9, 9, False)] > This list comprehension is basically interpreted like so: [(x,y,z) for x in range(1,10) for y in range(x,10) for z in (range(y,10), x+y==z)] To be more precise, the comma at the end is part of a tuple (you can omit parentheses of a tuple in many cases). This makes the final for loop iterate over the tuple (range(y, 10), x + y == z). You'll notice that this only works if the variable 'z' is already defined, since the tuple isn't constructed in the for loop. In other words, if we just run the code in a clean interpreter we'll get a NameError: Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win32 Type "copyright", "credits" or "license()" for more information. >>> [(x,y,z) for x in range(1,10) for y in range(x,10) for z in range(y,10), x+y==z] Traceback (most recent call last): File "", line 1, in [(x,y,z) for x in range(1,10) for y in range(x,10) for z in range(y,10), x+y==z] NameError: name 'z' is not defined What happened in your case is probably you were running different variations of the list comprehension in the same interpreter session. Since the iterating variable in a for loop still exists after the for loop exits, we won't encounter this error if we run a slightly different list comprehension first: Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win32 Type "copyright", "credits" or "license()" for more information. >>> [(x,y,z) for x in range(1,10) for y in range(x,10) for z in range(y,10) if x+y==z] [(1, 1, 2), (1, 2, 3), (1, 3, 4), (1, 4, 5), (1, 5, 6), (1, 6, 7), (1, 7, 8), (1, 8, 9), (2, 2, 4), (2, 3, 5), (2, 4, 6), (2, 5, 7), (2, 6, 8), (2, 7, 9), (3, 3, 6), (3, 4, 7), (3, 5, 8), (3, 6, 9), (4, 4, 8), (4, 5, 9)] >>> z 9 >>> As you can see, z exists after we run a for loop with z in it. Its value is still at the value it had during the last iteration. The same applies to x and y. Looking at your output, you had values of x, y and z in your interpreter session such that x + y == z evaluated to False. So the third value in your tuples is cycling between range(y, 10) and False. HTH, Hugo ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] "Strange" behaviour of list comprehension
Mahadevan, Anand wrote: > I'm playing around with list comprehension and in IDLE typed this in. I > actually wanted it to return all tuples satisfying the condition where z > is the sum of x and y. I kind of got mixed up with the syntax, hence I put > a comma in there instead of an "if". I'd like some assistance > understanding what it's doing... Thanks! > somelist = [(x,y,z) for x in range(1,10) for y in range(x,10) for z in range(y,10), x+y==z] somelist If you're puzzled about a list comprehension, try translating it into for loops: somelist = [] for x in range(1, 10): for y in range(x, 10): for z in range(y, 10), x+y==z: somelist.append((x, y, z)) In the first iteration you get x=1, y=1, so let's see what the inner loop gives: >>> x = y = 1 >>> for z in range(y, 10), x+y==z: ... print z ... Traceback (most recent call last): File "", line 1, in NameError: name 'z' is not defined So if you don't get a NameError you have defined z before entering the inner "loop". Let's fix that: >>> z = 42 >>> for z in range(y, 10), x+y==z: ... print z ... [1, 2, 3, 4, 5, 6, 7, 8, 9] False It should be obvious now that Python interprets range(y, 10), x+y==z as a tuple and iterates over that. range(1, 10) is a list in Python 2, so you are getting that first, then follows a boolean expression x+y == z which gives either True or False. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] "Strange" behaviour of list comprehension
On 13 February 2013 13:45, Mahadevan, Anand wrote: > I'm playing around with list comprehension and in IDLE typed this in. I > actually wanted it to return all tuples satisfying the condition where z is > the sum of x and y. I kind of got mixed up with the syntax, hence I put a > comma in there instead of an "if". I'd like some assistance understanding > what it's doing... > Thanks! > somelist = [(x,y,z) for x in range(1,10) for y in range(x,10) for z in range(y,10), x+y==z] This line doesn't actually work if you paste it into a fresh interpreter: >>> somelist = [(x,y,z) for x in range(1,10) for y in range(x,10) for z in >>> range(y,10), x+y==z] Traceback (most recent call last): File "", line 1, in NameError: name 'z' is not defined The clause at the end x+y==z should be preceded by 'if' rather than a comma. Commas separate function arguments and elements of collections in displays. Expressions separated by commas without brackets are interpreted as tuples: >>> a = 1, 0 >>> a (1, 0) So your outermost loop is over a tuple (range(y, 10), x+y==z): >>> [x for x in 1, 2] [1, 2] >>> [x for x in 'a', 'w', 'b'] ['a', 'w', 'b'] >>> [x for x in range(3), False] [[0, 1, 2], False] Which explains the output you get: somelist > [(1, 1, [1, 2, 3, 4, 5, 6, 7, 8, 9]), (1, 1, False), (1, 2, [2, 3, 4, 5, 6, > 7, 8, 9]), (1, 2, False), (1, 3, [3, 4, 5, 6, 7, 8, 9]), (1, 3, False), (1, > 4, [4, 5, 6, 7, 8, 9]), (1, 4, False), (1, 5, [5, 6, 7, 8, 9]), (1, 5, > False), (1, 6, [6, 7, 8, 9]), (1, 6, False), (1, 7, [7, 8, 9]), (1, 7, > False), (1, 8, [8, 9]), (1, 8, False), (1, 9, [9]), (1, 9, False), (2, 2, [2, > 3, 4, 5, 6, 7, 8, 9]), (2, 2, False), (2, 3, [3, 4, 5, 6, 7, 8, 9]), (2, 3, > False), (2, 4, [4, 5, 6, 7, 8, 9]), (2, 4, False), (2, 5, [5, 6, 7, 8, 9]), > (2, 5, False), (2, 6, [6, 7, 8, 9]), (2, 6, False), (2, 7, [7, 8, 9]), (2, 7, > False), (2, 8, [8, 9]), (2, 8, False), (2, 9, [9]), (2, 9, False), (3, 3, [3, > 4, 5, 6, 7, 8, 9]), (3, 3, False), (3, 4, [4, 5, 6, 7, 8, 9]), (3, 4, False), > (3, 5, [5, 6, 7, 8, 9]), (3, 5, False), (3, 6, [6, 7, 8, 9]), (3, 6, False), > (3, 7, [7, 8, 9]), (3, 7, False), (3, 8, [8, 9]), (3, 8, False), (3, 9, [9]), > (3, 9, False), (4, 4, [4, 5, 6, 7, 8, 9]), (4, 4, False), (4, 5, [5, 6, 7, 8, > 9]), (4 > , 5, False), (4, 6, [6, 7, 8, 9]), (4, 6, False), (4, 7, [7, 8, 9]), (4, 7, > False), (4, 8, [8, 9]), (4, 8, False), (4, 9, [9]), (4, 9, False), (5, 5, [5, > 6, 7, 8, 9]), (5, 5, False), (5, 6, [6, 7, 8, 9]), (5, 6, False), (5, 7, [7, > 8, 9]), (5, 7, False), (5, 8, [8, 9]), (5, 8, False), (5, 9, [9]), (5, 9, > False), (6, 6, [6, 7, 8, 9]), (6, 6, False), (6, 7, [7, 8, 9]), (6, 7, > False), (6, 8, [8, 9]), (6, 8, False), (6, 9, [9]), (6, 9, False), (7, 7, [7, > 8, 9]), (7, 7, False), (7, 8, [8, 9]), (7, 8, False), (7, 9, [9]), (7, 9, > False), (8, 8, [8, 9]), (8, 8, False), (8, 9, [9]), (8, 9, False), (9, 9, > [9]), (9, 9, False)] If you put the 'if' keyword in place of the comma it should work: >>> [x for x in 'a', 'w', 'b' if x != 'b'] ['a', 'w'] Oscar ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
[Tutor] "Strange" behaviour of list comprehension
I'm playing around with list comprehension and in IDLE typed this in. I actually wanted it to return all tuples satisfying the condition where z is the sum of x and y. I kind of got mixed up with the syntax, hence I put a comma in there instead of an "if". I'd like some assistance understanding what it's doing... Thanks! >>> somelist = [(x,y,z) for x in range(1,10) for y in range(x,10) for z in >>> range(y,10), x+y==z] >>> somelist [(1, 1, [1, 2, 3, 4, 5, 6, 7, 8, 9]), (1, 1, False), (1, 2, [2, 3, 4, 5, 6, 7, 8, 9]), (1, 2, False), (1, 3, [3, 4, 5, 6, 7, 8, 9]), (1, 3, False), (1, 4, [4, 5, 6, 7, 8, 9]), (1, 4, False), (1, 5, [5, 6, 7, 8, 9]), (1, 5, False), (1, 6, [6, 7, 8, 9]), (1, 6, False), (1, 7, [7, 8, 9]), (1, 7, False), (1, 8, [8, 9]), (1, 8, False), (1, 9, [9]), (1, 9, False), (2, 2, [2, 3, 4, 5, 6, 7, 8, 9]), (2, 2, False), (2, 3, [3, 4, 5, 6, 7, 8, 9]), (2, 3, False), (2, 4, [4, 5, 6, 7, 8, 9]), (2, 4, False), (2, 5, [5, 6, 7, 8, 9]), (2, 5, False), (2, 6, [6, 7, 8, 9]), (2, 6, False), (2, 7, [7, 8, 9]), (2, 7, False), (2, 8, [8, 9]), (2, 8, False), (2, 9, [9]), (2, 9, False), (3, 3, [3, 4, 5, 6, 7, 8, 9]), (3, 3, False), (3, 4, [4, 5, 6, 7, 8, 9]), (3, 4, False), (3, 5, [5, 6, 7, 8, 9]), (3, 5, False), (3, 6, [6, 7, 8, 9]), (3, 6, False), (3, 7, [7, 8, 9]), (3, 7, False), (3, 8, [8, 9]), (3, 8, False), (3, 9, [9]), (3, 9, False), (4, 4, [4, 5, 6, 7, 8, 9]), (4, 4, False), (4, 5, [5, 6, 7, 8, 9]), (4 , 5, False), (4, 6, [6, 7, 8, 9]), (4, 6, False), (4, 7, [7, 8, 9]), (4, 7, False), (4, 8, [8, 9]), (4, 8, False), (4, 9, [9]), (4, 9, False), (5, 5, [5, 6, 7, 8, 9]), (5, 5, False), (5, 6, [6, 7, 8, 9]), (5, 6, False), (5, 7, [7, 8, 9]), (5, 7, False), (5, 8, [8, 9]), (5, 8, False), (5, 9, [9]), (5, 9, False), (6, 6, [6, 7, 8, 9]), (6, 6, False), (6, 7, [7, 8, 9]), (6, 7, False), (6, 8, [8, 9]), (6, 8, False), (6, 9, [9]), (6, 9, False), (7, 7, [7, 8, 9]), (7, 7, False), (7, 8, [8, 9]), (7, 8, False), (7, 9, [9]), (7, 9, False), (8, 8, [8, 9]), (8, 8, False), (8, 9, [9]), (8, 9, False), (9, 9, [9]), (9, 9, False)] -This e-mail and any attachments may contain CONFIDENTIAL information, including PROTECTED HEALTH INFORMATION. If you are not the intended recipient, any use or disclosure of this information is STRICTLY PROHIBITED; you are requested to delete this e-mail and any attachments, notify the sender immediately, and notify the LabCorp Privacy Officer at privacyoffi...@labcorp.com or call (877) 23-HIPAA / (877) 234-4722. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor