A little help with List Comprehension

  • (2 Pages)
  • +
  • 1
  • 2

15 Replies - 1681 Views - Last Post: 16 October 2017 - 03:45 AM Rate Topic: -----

#1 CyberPat  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 25-September 14

A little help with List Comprehension

Posted 12 November 2014 - 03:07 AM

I know the concept.But my problem is i'm not so familiar with it.Like, from what i read, the syntax is :

[Y for x in LIST]

Where Y is commonly referred to as output function, x is variable and list is considered a set input.Now my question was,how does the following code work :

[x for x in range(51)

What does the first x do here?If it was x * 2, all of the numbers would be multiplied by 2.But when x is alone(no expression after it), what does it do?

I would gladly appreciate anyone who could be kind and enlighten me.Thank you so much.

Is This A Good Question/Topic? 0
  • +

Replies To: A little help with List Comprehension

#2 Peter O  Icon User is offline

  • D.I.C Regular

Reputation: 128
  • View blog
  • Posts: 298
  • Joined: 19-October 13

Re: A little help with List Comprehension

Posted 12 November 2014 - 03:28 AM

[x for x in range(51)]
 ^ ^
 | |
 | For each x in range(51) ...
 |
 ... output x.


So in other words this will output the same as range(51).
Was This Post Helpful? 1
  • +
  • -

#3 andrewsw  Icon User is online

  • the case is sol-ved
  • member icon

Reputation: 6379
  • View blog
  • Posts: 25,770
  • Joined: 12-December 12

Re: A little help with List Comprehension

Posted 12 November 2014 - 04:12 AM

The first statement won't work. Try:
print([y for x in range(51)])

to receive

Quote

NameError: global name 'y' is not defined

print([x for x in range(51)])

will work, as will
print([x*2 for x in range(51)])

so the first part - the output - is an expression based on the generated output of the list on the right.

http://www.pythonfor...sions-in-python
Was This Post Helpful? 2
  • +
  • -

#4 jon.kiparsky  Icon User is online

  • Chinga la migra
  • member icon


Reputation: 10685
  • View blog
  • Posts: 18,302
  • Joined: 19-March 11

Re: A little help with List Comprehension

Posted 12 November 2014 - 08:48 AM

View Postandrewsw, on 12 November 2014 - 06:12 AM, said:

The first statement won't work. Try:
print([y for x in range(51)])

to receive

Quote

NameError: global name 'y' is not defined

print([x for x in range(51)])

will work, as will
print([x*2 for x in range(51)])

so the first part - the output - is an expression based on the generated output of the list on the right.

http://www.pythonfor...sions-in-python


Perhaps the OP meant Y to be "some function producing output"? In that case, the resulting list would be "whatever the output of Y was, 51 times". For example:

>>> def y ():
...   return "Y output"
... 
>>> [y() for x in range(10)]
['Y output', 'Y output', 'Y output', 'Y output', 'Y output', 'Y output', 'Y output', 'Y output', 'Y output', 'Y output']
>>> 



or:


>>> def y ():
...   return x * x
...
>>> [y() for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> 



In any case, probably the easiest way to understand the list comprehension is to unroll it into the notionally equivalent loop:

[x for x in range (10)]


is equivalent to

l = []
for x in range (10):
  l.append(x)



So if you can reason about a loop, you can reason about a list comprehension.
Was This Post Helpful? 1
  • +
  • -

#5 andrewsw  Icon User is online

  • the case is sol-ved
  • member icon

Reputation: 6379
  • View blog
  • Posts: 25,770
  • Joined: 12-December 12

Re: A little help with List Comprehension

Posted 12 November 2014 - 10:16 AM

Jon's second example should be:
def y(x):
    return x * x
print([y(x) for x in range(10)])

Was This Post Helpful? 0
  • +
  • -

#6 jon.kiparsky  Icon User is online

  • Chinga la migra
  • member icon


Reputation: 10685
  • View blog
  • Posts: 18,302
  • Joined: 19-March 11

Re: A little help with List Comprehension

Posted 12 November 2014 - 10:34 AM

View Postandrewsw, on 12 November 2014 - 12:16 PM, said:

Jon's second example should be:
def y(x):
    return x * x
print([y(x) for x in range(10)])



Why would I need the print statement? As for the x parameter on the y function, it's actually not required here: that's the point of the example.
Was This Post Helpful? 1
  • +
  • -

#7 andrewsw  Icon User is online

  • the case is sol-ved
  • member icon

Reputation: 6379
  • View blog
  • Posts: 25,770
  • Joined: 12-December 12

Re: A little help with List Comprehension

Posted 12 November 2014 - 10:44 AM

The print() is just if this code is not being run from a Python command (IDLE).

The original code won't run because the global x (in y()) hasn't been defined. Maybe I'm missing something?
Was This Post Helpful? 1
  • +
  • -

#8 jon.kiparsky  Icon User is online

  • Chinga la migra
  • member icon


Reputation: 10685
  • View blog
  • Posts: 18,302
  • Joined: 19-March 11

Re: A little help with List Comprehension

Posted 12 November 2014 - 01:39 PM

View Postandrewsw, on 12 November 2014 - 12:44 PM, said:

The original code won't run because the global x (in y()) hasn't been defined. Maybe I'm missing something?


Well, I did copy it out of the python interpreter, just as you see it. :)

What you're missing is how python handles local scopes. You can reference a variable from outside the scope, but you can only write to a local, or to a global that's explicitly brought in with a global declaration. So the function y can see some x that's in its scope and report its value - but if I tried to write to it, I'd have trouble:

>>> def z():
...   x = x+3
>>> for x in range (10):
...     z()
...     print x
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in z
UnboundLocalError: local variable 'x' referenced before assignment
>>> 


Basically, we're looking at the same scenario as this one:


>>> def y():
...   return x*x
... 
>>> del(x)
>>> y()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in y
NameError: global name 'x' is not defined
>>> x = 4
>>> y()
16
>>> 


In the first case, x is not declared, so it's an error. But when I set a value for x, python is happy to read it. However, I still can't write to it:
>>> z()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in z
UnboundLocalError: local variable 'x' referenced before assignment



...because python assumes that all writes are to locals. But of course, this works fine:

>>> def z2():
...   global x
...   x+=2
>>> x
4
>>> z2()
>>> x
6


Now, I should point out that my original y is a terrible function, and if I came across it in the real world, I'd take it out back and shoot it in the head. But as an example of how list comps work, it's okay.
Was This Post Helpful? 1
  • +
  • -

#9 andrewsw  Icon User is online

  • the case is sol-ved
  • member icon

Reputation: 6379
  • View blog
  • Posts: 25,770
  • Joined: 12-December 12

Re: A little help with List Comprehension

Posted 13 November 2014 - 11:40 AM

Yes, I know about scope ;)

I am still unable to run your example in either IDLE or the Python Interactive Shell:

Attached Image

I just don't see how x is leaking out of the comprehension..

Anyway, I ain't going to lose sleep over it, but it remains a mystery (to me) how you were able to run this.
Was This Post Helpful? 1
  • +
  • -

#10 jon.kiparsky  Icon User is online

  • Chinga la migra
  • member icon


Reputation: 10685
  • View blog
  • Posts: 18,302
  • Joined: 19-March 11

Re: A little help with List Comprehension

Posted 13 November 2014 - 11:53 AM

Hm. Looks like scope rules changed in python 3. So my example only goes for the python that people are actually using. :)/>


Python:

Python 2.7.5 (default, Mar  9 2014, 22:15:05) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def y():
...     return x*x
... 
>>> [y() for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> 



Python 3:

Python 3.3.4 (default, Mar 13 2014, 11:09:17) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def y():
...     return x*x
... 
>>> x = 4
>>> y()
16
>>> [y() for x in range (10)]
[16, 16, 16, 16, 16, 16, 16, 16, 16, 16]
>>> 

Was This Post Helpful? 1
  • +
  • -

#11 andrewsw  Icon User is online

  • the case is sol-ved
  • member icon

Reputation: 6379
  • View blog
  • Posts: 25,770
  • Joined: 12-December 12

Re: A little help with List Comprehension

Posted 13 November 2014 - 11:57 AM

Mystery solved :)
Was This Post Helpful? 1
  • +
  • -

#12 CyberPat  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 25-September 14

Re: A little help with List Comprehension

Posted 14 November 2014 - 11:55 AM

View Postandrewsw, on 12 November 2014 - 04:12 AM, said:

The first statement won't work. Try:
print([y for x in range(51)])

to receive

Quote

NameError: global name 'y' is not defined

print([x for x in range(51)])

will work, as will
print([x*2 for x in range(51)])

so the first part - the output - is an expression based on the generated output of the list on the right.

http://www.pythonfor...sions-in-python


Thank you so much for the great answer. Why is x considered an expression here? And why can't we set y as our out function?
Was This Post Helpful? 0
  • +
  • -

#13 andrewsw  Icon User is online

  • the case is sol-ved
  • member icon

Reputation: 6379
  • View blog
  • Posts: 25,770
  • Joined: 12-December 12

Re: A little help with List Comprehension

Posted 14 November 2014 - 12:01 PM

x is considered an expression because it results in a value - the output - just as x * 2 does.
[Y for x in LIST]

You can't use Y here because it hasn't been defined anywhere. Jon's examples demonstrate that you could use y() if you have already defined some function y() that returns a value.
Was This Post Helpful? 1
  • +
  • -

#14 CyberPat  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 25-September 14

Re: A little help with List Comprehension

Posted 14 November 2014 - 04:40 PM

Thanks! In fact,in the following list comprehension, the first x is kinda same as the loop variable and that's why we don't get a global name error while using it, am i right?

s = [x for x in range(51)
Was This Post Helpful? 0
  • +
  • -

#15 jon.kiparsky  Icon User is online

  • Chinga la migra
  • member icon


Reputation: 10685
  • View blog
  • Posts: 18,302
  • Joined: 19-March 11

Re: A little help with List Comprehension

Posted 14 November 2014 - 04:56 PM

yep. In fact, it is the same as the loop variable - basically, it can be an arbitrary python expression, and a variable counts as an expression (evaluating to the right-hand value of the variable)

Think about that post where I unrolled the listcomp for you: this is identical to

s = []
for x in range (51):
  s.append(x)



so you can see this as:


somelist = [ EXP for ITERATOR in ITERABLE ]


which is equivalent to

somelist = []
for ITERATOR in ITERABLE:
  somelist.append(EXP)


In both cases, the Expression's scope includes the ITERATOR. That's probably the weird part: you're used to having the iterator declared before we it's used. In the list comp, it comes after, but since the whole thing is parsed by the interpreter as one chunk, that's not a problem.
Was This Post Helpful? 1
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2