<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress/2.3.3" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>
<channel>
	<title>Comments on: generators != lists (?)</title>
	<link>http://www.zerbie.com/2008/03/25/generators-lists/</link>
	<description>crazy, some say</description>
	<pubDate>Wed, 19 Nov 2008 17:31:28 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.3.3</generator>
		<item>
		<title>By: ars</title>
		<link>http://www.zerbie.com/2008/03/25/generators-lists/#comment-14</link>
		<dc:creator>ars</dc:creator>
		<pubDate>Sat, 05 Apr 2008 02:02:01 +0000</pubDate>
		<guid>http://www.zerbie.com/2008/03/25/generators-lists/#comment-14</guid>
		<description>Generators are a nice and easy way to create iterators. Here's a silly example:

&lt;code&gt;
&#62;&#62;&#62; def gen():
...     yield 1
...     yield 2
...     yield 3
...
&#62;&#62;&#62; type(gen)

&#62;&#62;&#62; g = gen()
&#62;&#62;&#62; type(g)

&#62;&#62;&#62; g.next()
1
&#62;&#62;&#62; g.next()
2
&#62;&#62;&#62; g.next()
3
&#62;&#62;&#62; g.next()
Traceback (most recent call last):
  File "", line 1, in 
StopIteration
&lt;/code&gt;

Basically, gen is just a function. It's the yield statements that let python know it's a generator. g is the actual generator object created from calling gen(). 

Calling g.next() the first time returns the first value that's "yielded". The second time, the function just picks up where it left off, so g.next() returns 2, etc. Until it drops off the end, at which point it raises a StopIteration exception. This is kind how iterators work behind the scenes. Generators make it easier to write iterators without defining a class and the next, iter methods. 

You don't usually use a generator in that way. Instead you would use it like an iterator, like this:

&lt;code&gt;
&#62;&#62;&#62; for num in gen():
...     print num
...
1
2
3
&lt;/code&gt;

Anyway, to your post ...  showlinks() returns a generator object, and you could call next() or just iterate through it with a for loop. 

When you create a list (links = list(showlinks())), it's basically iterated through the entire generator and stuffed the values in that list.

Each element of the list is actually a an instance of the Link class from the mechanize package (twill is using mechanize for its browsing facilities):

&lt;code&gt;
&#62;&#62;&#62; link = links[1]
&#62;&#62;&#62; link
Link(base_url='http://del.icio.us', url='https://secure.del.icio.us/login', text='login',
tag='a', attrs=[('href', 'https://secure.del.icio.us/login')])
&#62;&#62;&#62; type(link)

&#62;&#62;&#62; link.__class__

&#62;&#62;&#62; dir(link)
['__cmp__', '__doc__', '__init__', '__module__', '__repr__', 'absolute_url', 'attrs', 'bas
e_url', 'tag', 'text', 'url']
&#62;&#62;&#62; link.url
'https://secure.del.icio.us/login'
&#62;&#62;&#62; link.text
'login'
&#62;&#62;&#62; link.absolute_url
'https://secure.del.icio.us/login'
&#62;&#62;&#62; link.tag
'a'
&lt;/code&gt;

Hope that makes sense.</description>
		<content:encoded><![CDATA[<p>Generators are a nice and easy way to create iterators. Here&#8217;s a silly example:</p>
<p><code><br />
&gt;&gt;&gt; def gen():<br />
...     yield 1<br />
...     yield 2<br />
...     yield 3<br />
...<br />
&gt;&gt;&gt; type(gen)</p>
<p>&gt;&gt;&gt; g = gen()<br />
&gt;&gt;&gt; type(g)</p>
<p>&gt;&gt;&gt; g.next()<br />
1<br />
&gt;&gt;&gt; g.next()<br />
2<br />
&gt;&gt;&gt; g.next()<br />
3<br />
&gt;&gt;&gt; g.next()<br />
Traceback (most recent call last):<br />
  File "", line 1, in<br />
StopIteration<br />
</code></p>
<p>Basically, gen is just a function. It&#8217;s the yield statements that let python know it&#8217;s a generator. g is the actual generator object created from calling gen(). </p>
<p>Calling g.next() the first time returns the first value that&#8217;s &#8220;yielded&#8221;. The second time, the function just picks up where it left off, so g.next() returns 2, etc. Until it drops off the end, at which point it raises a StopIteration exception. This is kind how iterators work behind the scenes. Generators make it easier to write iterators without defining a class and the next, iter methods. </p>
<p>You don&#8217;t usually use a generator in that way. Instead you would use it like an iterator, like this:</p>
<p><code><br />
&gt;&gt;&gt; for num in gen():<br />
...     print num<br />
...<br />
1<br />
2<br />
3<br />
</code></p>
<p>Anyway, to your post &#8230;  showlinks() returns a generator object, and you could call next() or just iterate through it with a for loop. </p>
<p>When you create a list (links = list(showlinks())), it&#8217;s basically iterated through the entire generator and stuffed the values in that list.</p>
<p>Each element of the list is actually a an instance of the Link class from the mechanize package (twill is using mechanize for its browsing facilities):</p>
<p><code><br />
&gt;&gt;&gt; link = links[1]<br />
&gt;&gt;&gt; link<br />
Link(base_url='http://del.icio.us', url='https://secure.del.icio.us/login', text='login',<br />
tag='a', attrs=[('href', 'https://secure.del.icio.us/login')])<br />
&gt;&gt;&gt; type(link)</p>
<p>&gt;&gt;&gt; link.__class__</p>
<p>&gt;&gt;&gt; dir(link)<br />
['__cmp__', '__doc__', '__init__', '__module__', '__repr__', 'absolute_url', 'attrs', 'bas<br />
e_url', 'tag', 'text', 'url']<br />
&gt;&gt;&gt; link.url<br />
'https://secure.del.icio.us/login'<br />
&gt;&gt;&gt; link.text<br />
'login'<br />
&gt;&gt;&gt; link.absolute_url<br />
'https://secure.del.icio.us/login'<br />
&gt;&gt;&gt; link.tag<br />
'a'<br />
</code></p>
<p>Hope that makes sense.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: nat</title>
		<link>http://www.zerbie.com/2008/03/25/generators-lists/#comment-13</link>
		<dc:creator>nat</dc:creator>
		<pubDate>Fri, 04 Apr 2008 18:26:48 +0000</pubDate>
		<guid>http://www.zerbie.com/2008/03/25/generators-lists/#comment-13</guid>
		<description>follow(list(links)[1].url) perhaps?</description>
		<content:encoded><![CDATA[<p>follow(list(links)[1].url) perhaps?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: pam</title>
		<link>http://www.zerbie.com/2008/03/25/generators-lists/#comment-11</link>
		<dc:creator>pam</dc:creator>
		<pubDate>Fri, 04 Apr 2008 17:12:44 +0000</pubDate>
		<guid>http://www.zerbie.com/2008/03/25/generators-lists/#comment-11</guid>
		<description>Hmmm. I think my problem is that showlinks() gives me something like this:

1. None ==&gt; /20484

Where the number is dynamically generated. I am not sure how to follow that link.</description>
		<content:encoded><![CDATA[<p>Hmmm. I think my problem is that showlinks() gives me something like this:</p>
<p>1. None ==> /20484</p>
<p>Where the number is dynamically generated. I am not sure how to follow that link.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: nat</title>
		<link>http://www.zerbie.com/2008/03/25/generators-lists/#comment-7</link>
		<dc:creator>nat</dc:creator>
		<pubDate>Fri, 04 Apr 2008 15:27:16 +0000</pubDate>
		<guid>http://www.zerbie.com/2008/03/25/generators-lists/#comment-7</guid>
		<description>follow() doesn't just use the name of the link, you can also give it the link text, or the url, hell, even just part of the url. really anything that distinguishes it.</description>
		<content:encoded><![CDATA[<p>follow() doesn&#8217;t just use the name of the link, you can also give it the link text, or the url, hell, even just part of the url. really anything that distinguishes it.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
