<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Perused</title>
	
	<link>http://blog.jeroenpelgrims.be</link>
	<description>What I learned and discovered</description>
	<lastBuildDate>Sun, 20 Nov 2011 22:27:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/perused" /><feedburner:info uri="perused" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Updated SoundSwitch</title>
		<link>http://feedproxy.google.com/~r/perused/~3/HJGmDjO7pOY/</link>
		<comments>http://blog.jeroenpelgrims.be/2011/06/updated-soundswitch/#comments</comments>
		<pubDate>Thu, 23 Jun 2011 19:39:59 +0000</pubDate>
		<dc:creator>Jeroen</dc:creator>
				<category><![CDATA[.NET]]></category>

		<guid isPermaLink="false">http://blog.jeroenpelgrims.be/?p=643</guid>
		<description><![CDATA[I updated my SoundSwitch Application. You can install it by going here. The purpose of SoundSwitch is to be able to easily switch between  2 or more Audio output devices. For example, I have a wireless headset and my regular speakers. Both are detected as a separate audio card in the sound panel. The only [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.jeroenpelgrims.be/wp-content/uploads/2011/06/arrow_switch.png"><img class="alignleft size-full wp-image-645" title="arrow_switch" src="http://blog.jeroenpelgrims.be/wp-content/uploads/2011/06/arrow_switch.png" alt="" width="32" height="32" /></a></p>
<p>I updated my <a href="http://soundswitch.codeplex.com/">SoundSwitch</a> Application.<br />
You can install it by going <a href="http://soundswitch.codeplex.com/releases/">here</a>.</p>
<p>The purpose of SoundSwitch is to be able to easily switch between  2 or more Audio output devices.<br />
For example, I have a wireless headset and my regular speakers.<br />
Both are detected as a separate audio card in the sound panel.<br />
The only way to switch between them is to open the playback devices panel and select one of them and choose to put it as default device.</p>
<p>That&#8217;s such a hassle!<br />
With SoundSwitch you just press Ctrl+Alt+F11 and it toggles between the cards you selected.</p>
<p>Todos:</p>
<ol>
<li>Let the application start up when the user logs in. (currently you have to start it yourself)</li>
<li> Allow users to set their own shortcut (instead of  Ctrl+Alt+F11)</li>
<li>Make the configuration easier. (Won&#8217;t be possible I&#8217;m afraid though)</li>
</ol>
<p><span style="color: #ff0000;"><strong>UPDATE:<br />
</strong></span>Changed the hosting to CodePlex, apparently you can host ClickOnce applications there!</p>

<p><a href="http://feedads.g.doubleclick.net/~a/q5gt4rrKFHYLZDUDdAMagmXYfsg/0/da"><img src="http://feedads.g.doubleclick.net/~a/q5gt4rrKFHYLZDUDdAMagmXYfsg/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/q5gt4rrKFHYLZDUDdAMagmXYfsg/1/da"><img src="http://feedads.g.doubleclick.net/~a/q5gt4rrKFHYLZDUDdAMagmXYfsg/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/perused/~4/HJGmDjO7pOY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.jeroenpelgrims.be/2011/06/updated-soundswitch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.jeroenpelgrims.be/2011/06/updated-soundswitch/</feedburner:origLink></item>
		<item>
		<title>jQuery scroll to element plugin</title>
		<link>http://feedproxy.google.com/~r/perused/~3/Z3X49fwwoIg/</link>
		<comments>http://blog.jeroenpelgrims.be/2011/06/jquery-scroll-to-element-plugin/#comments</comments>
		<pubDate>Tue, 14 Jun 2011 02:13:53 +0000</pubDate>
		<dc:creator>Jeroen</dc:creator>
				<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://blog.jeroenpelgrims.be/?p=637</guid>
		<description><![CDATA[$.fn.scrollTo = function&#40;duration&#41;&#123; if&#40;duration == null&#41;&#123; duration = 1000; &#125; &#160; var offset = $&#40;this&#41;.offset&#40;&#41;.top - $&#40;window&#41;.height&#40;&#41;/2 + $&#40;this&#41;.height&#40;&#41;; $&#40;'html,body'&#41;.animate&#40;&#123; scrollTop: offset &#125;, duration&#41;; &#125; This small plugin will scroll to a selected element when calling .scrollTo() on it. It has an optional parameter which specifies the duration of the scroll. For example, if i [...]]]></description>
			<content:encoded><![CDATA[
<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$.<span style="color: #660066;">fn</span>.<span style="color: #660066;">scrollTo</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>duration<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>duration <span style="color: #339933;">==</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        duration <span style="color: #339933;">=</span> <span style="color: #CC0000;">1000</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> offset <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">offset</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">top</span> <span style="color: #339933;">-</span> $<span style="color: #009900;">&#40;</span>window<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">height</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">/</span><span style="color: #CC0000;">2</span> <span style="color: #339933;">+</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">height</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'html,body'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">animate</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
       scrollTop<span style="color: #339933;">:</span> offset
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> duration<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This small plugin will scroll to a selected element when calling .scrollTo() on it.<br />
It has an optional parameter which specifies the duration of the scroll.</p>
<p>For example, if i would have a div with the id &#8220;#mydiv&#8221; I would let the screen scroll to it using this code:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#mydiv'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">scrollTo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">//Or, if you want the animation to be slower</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#mydiv'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">scrollTo</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">2000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The top of the selected element will be displayed at 50% of the screen unless the scrollbar is too short, then the element will be lower on the screen.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/chsMAR8aEoN5anzMGeJobQQluis/0/da"><img src="http://feedads.g.doubleclick.net/~a/chsMAR8aEoN5anzMGeJobQQluis/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/chsMAR8aEoN5anzMGeJobQQluis/1/da"><img src="http://feedads.g.doubleclick.net/~a/chsMAR8aEoN5anzMGeJobQQluis/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/perused/~4/Z3X49fwwoIg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.jeroenpelgrims.be/2011/06/jquery-scroll-to-element-plugin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.jeroenpelgrims.be/2011/06/jquery-scroll-to-element-plugin/</feedburner:origLink></item>
		<item>
		<title>Fridgemon – Keeping track of what’s in your fridge</title>
		<link>http://feedproxy.google.com/~r/perused/~3/x8yglUHrO_M/</link>
		<comments>http://blog.jeroenpelgrims.be/2011/04/fridgemon-keeping-track-of-whats-in-your-fridge/#comments</comments>
		<pubDate>Thu, 21 Apr 2011 22:10:51 +0000</pubDate>
		<dc:creator>Jeroen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.jeroenpelgrims.be/?p=626</guid>
		<description><![CDATA[On weekdays I live by myself in Brussels to be closer to the University. Of course, I have to do my own shopping and buy food supplies myself. I also have to keep track of what&#8217;s in my fridge and what&#8217;s expiring when. I suck at that. However, I&#8217;m good with computers. And computers are [...]]]></description>
			<content:encoded><![CDATA[<p>On weekdays I live by myself in Brussels to be closer to the University.<br />
Of course, I have to do my own shopping and buy food supplies myself.</p>
<p>I also have to keep track of what&#8217;s in my fridge and what&#8217;s expiring when.<br />
I suck at that.<br />
However, I&#8217;m good with computers. And computers are good at keeping track of stuff.<br />
So I created a small tool to do just that, <a href="http://fridgemon.appspot.com/">Fridgemon</a>.</p>
<p>I know it&#8217;s butt-ugly but it does it&#8217;s job.</p>
<div class="al2fb_likers"><a href="http://www.facebook.com/profile.php?id=653823971" rel="nofollow">Simon VdW</a> <span class="al2fb_liked">liked this post</span></div>
<p><a href="http://feedads.g.doubleclick.net/~a/llDsWIVVXMBX9f_ORNu4iI-FLWA/0/da"><img src="http://feedads.g.doubleclick.net/~a/llDsWIVVXMBX9f_ORNu4iI-FLWA/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/llDsWIVVXMBX9f_ORNu4iI-FLWA/1/da"><img src="http://feedads.g.doubleclick.net/~a/llDsWIVVXMBX9f_ORNu4iI-FLWA/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/perused/~4/x8yglUHrO_M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.jeroenpelgrims.be/2011/04/fridgemon-keeping-track-of-whats-in-your-fridge/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.jeroenpelgrims.be/2011/04/fridgemon-keeping-track-of-whats-in-your-fridge/</feedburner:origLink></item>
		<item>
		<title>Learning Norwegian – Some resources</title>
		<link>http://feedproxy.google.com/~r/perused/~3/0uRigatl9p8/</link>
		<comments>http://blog.jeroenpelgrims.be/2011/04/learning-norwegian-some-resources/#comments</comments>
		<pubDate>Mon, 18 Apr 2011 21:03:28 +0000</pubDate>
		<dc:creator>Jeroen</dc:creator>
				<category><![CDATA[Norwegian]]></category>

		<guid isPermaLink="false">http://blog.jeroenpelgrims.be/?p=517</guid>
		<description><![CDATA[With only 5 million speakers it&#8217;s not very easy to find resources on learning Norwegian compared to other languages. Listed below is a compilation of the resources I found while looking for learning materials. Norwegian is the first language I&#8217;m consciously learning on my own, not in a school environment. (I say consciously because I [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-medium wp-image-601" title="Norway Flag" src="http://blog.jeroenpelgrims.be/wp-content/uploads/2011/04/Norway_Grunge_Flag_by_think0-e1302983016655-300x187.jpg" alt="" width="130" height="81" />With only 5 million speakers it&#8217;s not very easy to find resources on learning Norwegian compared to other languages. Listed below is a compilation of the resources I found while looking for learning materials. Norwegian is the first language I&#8217;m consciously learning on my own, not in a school environment. (I say consciously because I learned English by watching a load of movies and series, I didn&#8217;t really have to make an effort then) I&#8217;m currently a complete beginner in Norwegian with only 25/30 Pimsleur lessons done and some extra vocabulary with Anki. <span id="more-517"></span></p>
<h2>Textbooks</h2>
<p>Full fledged learning tools containing a textbook explaining grammar and spelling rules, audio tapes for pronunciation and often also workbooks to apply the acquired knowledge.</p>
<h4><a href="http://www.amazon.com/gp/product/0743566300/ref=as_li_ss_tl?ie=UTF8&amp;tag=perused-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0743566300">Pimsleur Norwegian</a></h4>
<p>30 audio lessons of 30 minutes each. I started learning with this. After each lesson of Pimsleur&#8217;s completed I could clearly notice that I had learned something. The rate at which I learned stuff using Pimsleur is very high. Unfortunately Pimsleur Norwegian has only 1 level of lessons, compared to 2 or 3 levels for larger languages like French or Chinese. If I had to suggest a starting point to learning Norwegian, this would be it. <a href="http://www.pimsleur.com/Learn-Norwegian">Pimsleur Norwegian website </a></p>
<h4><a href="http://www.amazon.com/gp/product/8211001233/ref=as_li_ss_tl?ie=UTF8&amp;tag=perused-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=8211001233">Ny I Norge</a> &amp; <a href="http://www.amazon.com/gp/product/8211000121/ref=as_li_qf_sp_asin_tl?ie=UTF8&amp;tag=perused-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=8211000121">Bo I Norge</a></h4>
<p>Ny I Norge contains a textbook, audio readings of the conversations in the textbook, a workbook and listening comprehension exercises. Bo I Norge is a textbook for more advanced learners (after Ny I Norge). This will be the second resource I&#8217;ll be using, after Pimsleur.</p>
<h4><a href="http://www.amazon.com/gp/product/0415110114/ref=as_li_qf_sp_asin_tl?ie=UTF8&amp;tag=perused-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0415110114">Colloquial Norwegian</a></h4>
<p>Similar to Ny I Norge, consists of a textbook with exercises and audio readings. I do have the impression that the learning curve of the book is higher.</p>
<h4><a href="http://www.cappelendammundervisning.no/undervisning/project-detail.action?id=7030">På vei</a>, <a href="http://www.cappelendammundervisning.no/undervisning/project-detail.action?id=1962">Stein På Stein</a>, <a href="http://www.cappelendammundervisning.no/undervisning/project-detail.action?id=7045">Her på berget</a></h4>
<p>All three books consist of a textbook, a workbook and audio files. They consist of three levels of which På vei is the 1st, Stein På Stein the second and finally Her på berget the third. Each of the books have free exercises online. (<a href="http://pavei.cappelen.no/">På vei</a>, <a href="http://steinpastein.cappelendamm.no/">Stein På Stein</a>, <a href="http://herpaberget.cappelendamm.no/">Her på berget</a>)</p>
<h4>Praktisk Norsk <a href="http://www.cappelendammundervisning.no/undervisning/product-detail.action?id=128624">I</a> &amp; <a href="http://www.cappelendammundervisning.no/undervisning/product-detail.action?id=128559">II</a></h4>
<p>From the same series as På vei etc. Also has free exercises online <a href="http://praktisknorsk1.cappelendamm.no/">here</a> and <a href="http://praktisknorsk2.cappelendamm.no/">here</a>.</p>
<h4><a href="http://www.amazon.com/gp/product/0340887575/ref=as_li_qf_sp_asin_tl?ie=UTF8&amp;tag=perused-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0340887575">Teach Yourself Norwegian</a></h4>
<p>A book with conversations both in English and in Norwegian. Seems to rely heavily of cross referencing the dialogues in both languages. Also contains audio recordings for the conversations.</p>
<h4><a href="http://norwords.com/textbook/index.html">Sett i gang I &amp; II</a></h4>
<p>A textbook, workbook and audio files. The audio files are freely downloadable <a href="http://norwords.com/guides/index.html">here</a> and <a href="http://norwords.com/guides2/index.html">here</a>.</p>
<h4><a title="My Little Norway" href="http://mylittlenorway.com/learn-norwegian/">My Little Norway</a></h4>
<p>A blog about 2 people in Norway, one native speaker and one who&#8217;s learning Norwegian. They also have a bunch of lessons on the blog for learning Norwegian.</p>
<h4>Assimil (for German or French speakers)</h4>
<p><a href="http://www.amazon.com/gp/product/3896252100/ref=as_li_qf_sp_asin_tl?ie=UTF8&amp;tag=perused-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=3896252100">Norwegisch ohne Mühe</a> (For German speakers) | <a href="http://www.assimil.com/descriptionProduitDetail.do?paramIdProduit=1441&amp;paramIdMethode=1441">Assimil site</a> <a href="http://www.amazon.com/gp/product/0320068196/ref=as_li_qf_sp_asin_tl?ie=UTF8&amp;tag=perused-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0320068196">Le Norvegien sans Peine</a>(For French speakers)</p>
<h2>Television</h2>
<h4><a href="http://www.nrk.no/nett-tv/">NRK</a></h4>
<p>NRK is the Norwegian national broadcaster. A lot of the programs are visible freely (Click A-Å on the top and choose a starting letter of a program). For example, <a href="http://www.nrk.no/nett-tv/klipp/729601/">the news</a>is something that is updated daily.</p>
<h4><a href="http://video.nrkbeta.no/torrents/">NRK Torrents </a></h4>
<p>NRK also offers some HD torrents of their programs. These don&#8217;t get updated very often I&#8217;ve noticed.</p>
<h4><a href="http://www.tv3play.no/program">TV3</a></h4>
<p>TV3 broadcasts more foreign (to Norway) programs which are more limited by drm. But those are most likely not the programs you want to watch anyways cause they are in different languages :) Watch out, they also have some Swedish programs.</p>
<h4><a href="http://webtv.tvnorge.no/">TVNorge</a> (NOT FREE)</h4>
<h4><a href="http://www.tv2.no/play/">TV2</a> (SEMI-FREE)</h4>
<p>Only short clips of programs are free, full programs require a subscription.</p>
<h2>Radio</h2>
<ul>
<li><a href="http://www.radionorge.com/">Radio Norge</a></li>
<li><a href="http://www.nrk.no/p1/">NRK P1</a> &#8211; Click the small red round button with the play icon to the right</li>
<li><a href="http://www.nrk.no/p2/">NRK P2</a> &#8211; Click the small red round button with the play icon to the right</li>
<li><a href="http://p3.no/">NRK Petre</a> (P3)</li>
<li><a href="http://www.nrk.no/alltid_nyheter/">NRK Alltid nyheter</a> (always news) &#8211; Click &#8220;Nettradio&#8221; in the left bar.</li>
<li><a href="http://www.nrk.no/klassisk/">NRK Klassisk</a></li>
<li><a href="http://www.p4.no/">P4 Radio Hele Norge</a> &#8211; Click &#8220;lytt nå&#8221;</li>
<li><a href="http://www.nrk.no/radio/">All NRK Radio channels</a></li>
<li><a href="http://www.radiolist.net/norway">A huge list of other norwegian radio channels</a></li>
</ul>
<h2>Extra resources</h2>
<h4><a href="http://ankisrs.net/">Anki flashcards</a></h4>
<p>Anki is a program to exercise flashcards using <a href="http://en.wikipedia.org/wiki/Spaced_repetition">spaced repetition</a>. I use this to exercise vocabulary. The great thing about Anki is that you can also add audio files to your flashcards, so you can train pronunciation and spelling in one go. I don&#8217;t like having to record every word manually, so I made <a href="http://bulktts.appspot.com/">this site</a> to automatically generate sound files for words you type in. <a href="http://en.wiktionary.org/wiki/Wiktionary:Frequency_lists/Norwegian">Here</a> is a list of the 1000 most used Norwegian words to get you started. Be sure to use Bokm<a href="http://en.wikipedia.org/wiki/Bokmaal_and_Nynorsk#Bokm.C3.A5l_and_Nynorsk">å</a>l (see below).</p>
<h4>News in &#8220;Simple Norwegian&#8221;</h4>
<p><a href="http://www.klartale.no/">Klar Tale</a>is a news website written in simple Norwegian. If you use their website together with a browser plugin which can translate (unknown) words you select then this is another good way of learning.</p>
<h4>Lessons on Youtube</h4>
<p><a href="http://www.youtube.com/user/Crienexzy">Crienexzy</a>on Youtube has a bunch of videos on Norwegian pronunciation. She&#8217;s also a fine example of Scandinavian beauty.</p>
<h4>Films</h4>
<p>A great way to passively (but slowly) learn is by watching movies and series. Some Norwegian films I liked were:</p>
<ul>
<li><a href="http://www.imdb.com/title/tt1255956/">Vegas</a></li>
<li><a href="http://www.imdb.com/title/tt1740707/">Trolljegeren</a></li>
<li><a href="http://www.imdb.com/title/tt1278340/">Død snø</a></li>
<li>Fritt Vilt <a href="http://www.imdb.com/title/tt0808276/">I</a>, <a href="http://www.imdb.com/title/tt1188990/">II</a>, <a href="http://www.imdb.com/title/tt1464535/">III</a></li>
</ul>
<p>A big list of Norwegian films can be found <a href="http://www.imdb.com/search/title?languages=no|1&amp;title_type=feature&amp;sort=moviemeter,asc">on IMDB</a>.</p>
<h4><a href="http://www.livemocha.com/">Livemocha</a></h4>
<p>Livemocha uses the same teaching style as Rosetta Stone. I&#8217;m not particularly fond of this way of learning, I learned a bunch more by just a few lessons of Pimsleur. However, it&#8217;s a great way to find native speaking partners.</p>
<h4><a title="Interpals" href="http://interpals.net">Interpals</a></h4>
<p>A site aimed at bringing penpals together. Has quite a large user base.</p>
<h4>Linguistic tools &amp; sound files of Norwegian dialects</h4>
<p><a href="http://www.ling.hf.ntnu.no/">This site</a> contains <a href="http://www.ling.hf.ntnu.no/forskning/norsource/service.html">a tool</a> to break down sentence structure and some <a href="http://www.ling.hf.ntnu.no/nos_files/mp3/">sound files</a> of texts in various Norwegian dialects. I think it should be accessible  through <a href="http://www.ling.hf.ntnu.no/nos_ny/">this site</a> as well, but that one seems to have some database problems atm. Books about norwegian dialects can be found <a href="http://www.bokkilden.no/SamboWeb/emneliste.do?emnekode=8.1.8.2">here</a>.</p>
<h4>Free music</h4>
<p>Gatas Parlament is a Norwegian rap group and they offer their music for free on <a href="http://www.gatasp.no/diskografi/">their website</a>.</p>
<h4>More info</h4>
<p><a href="http://norwegianlanguage.info/index.html">This site</a>has a bunch of links to Norwegian related things.</p>
<h2>Bokmål &amp; Nynorsk</h2>
<p>Norwegian has 2 written forms, <a href="http://en.wikipedia.org/wiki/Bokmaal_and_Nynorsk#Bokm.C3.A5l_and_Nynorsk">Bokmål and Nynorsk</a>. Unlike what Nynorsk&#8217;s (new-Norwegian) name seems to suggest it is actually older than Bokmål. The grand majority of (newly) written material is in Bokmål, so you&#8217;ll have the most use of learning Bokmål. As far as I know, all textbooks listed above use Bokmål.</p>
<h2>Get started</h2>
<p>I found a <a href="http://thepiratebay.org/torrent/6327675">torrent</a> which contains a lot of the resources mentioned above. Credit where credit is due: a lot of the resources mentioned here came from <a href="http://www.reddit.com/r/Norway/comments/gfh4v/id_love_to_learn_the_basics_of_norwegian_where/c1n70ok">this post</a> on reddit. <span style="color: #ff0000;"><strong>Update</strong></span> Found <a href="http://www.stolaf.edu/depts/norwegian/grammar/index.html">a site</a> with good explanations on grammar rules. And <a title="Verbix conjugations" href="http://www.verbix.com/languages/norwegian.shtml">a site</a> which will show you ALL conjugations of a given verb! Super useful.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/npPbxDct6NuTdpAv6CoUhfSHfa4/0/da"><img src="http://feedads.g.doubleclick.net/~a/npPbxDct6NuTdpAv6CoUhfSHfa4/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/npPbxDct6NuTdpAv6CoUhfSHfa4/1/da"><img src="http://feedads.g.doubleclick.net/~a/npPbxDct6NuTdpAv6CoUhfSHfa4/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/perused/~4/0uRigatl9p8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.jeroenpelgrims.be/2011/04/learning-norwegian-some-resources/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.jeroenpelgrims.be/2011/04/learning-norwegian-some-resources/</feedburner:origLink></item>
		<item>
		<title>Bulktts – Text to speech using Google Translate</title>
		<link>http://feedproxy.google.com/~r/perused/~3/VMNR9xbYmMo/</link>
		<comments>http://blog.jeroenpelgrims.be/2011/03/bulktts-text-to-speech-using-google-translate/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 02:47:47 +0000</pubDate>
		<dc:creator>Jeroen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.jeroenpelgrims.be/?p=506</guid>
		<description><![CDATA[The project I was talking about in the previous post was this one, bulktts. With Google Translate you can only listen to the sound of the text you typed in, but you can&#8217;t download it. I found a url which with the right parameters lets you download the mp3 file generated by Google Translate, but [...]]]></description>
			<content:encoded><![CDATA[<p>The project I was talking about in the previous post was this one, <a href="http://bulktts.appspot.com">bulktts</a>.<br />
With Google Translate you can only listen to the sound of the text you typed in, but you can&#8217;t download it.<br />
I found a url which with the right parameters lets you download the mp3 file generated by Google Translate, but if you need a bunch of words converted to speech this is a a tedious job of changing the url, save as.. etc.</p>
<p>Bulktts allows you to choose a language, paste your list of words in and download a zip file with the mp3&#8242;s.</p>
<p><del>There are still some bugs though, at the moment words with special characters won&#8217;t product the correct sound.<br />
</del>Update: Sound bug fixed. Only the filenames for special character words in zip files are still not correct.</p>
<div style="font-size: 12px; color: #cccccc; background-color: #0000ff; font-family: &quot;Trebuchet MS&quot;, &quot;Helvetica&quot;, sans-serif; line-height: 100%; opacity: 1; border-top-left-radius: 7px; border-top-right-radius: 7px; border-bottom-right-radius: 7px; border-bottom-left-radius: 7px; text-align: left; position: fixed; max-width: 400px; z-index: 2147480064; top: 97px; left: 560px; display: none; padding: 4px; border: 1px none #000000;">but<br />
<strong>conjunction</strong> <em>but, yet, however, still</em></div>
<div style="display: none; position: fixed; max-height: 27px; width: 450px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 2px; border-left-width: 2px; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 5px; background-color: #ffffff; overflow-x: auto; overflow-y: auto; min-height: 200px; z-index: 2147479936; text-align: center; color: #000000; right: 0px; top: 0px; border-color: #808080; border-style: dashed; padding: 3px;"><textarea style="height: 80px; width: 444px; padding: 2px; border: 1px solid rgba(7, 0, 0, 0);"></textarea>&nbsp;</p>
<select>
<option value="af">Afrikaans</option>
<option value="sq">Albanian</option>
<option value="ar">Arabic</option>
<option value="hy">Armenian</option>
<option value="az">Azerbaijani</option>
<option value="eu">Basque</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh-CN">Chinese (Simplified)</option>
<option value="zh-TW">Chinese (Traditional)</option>
<option value="hr">Croatian</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option selected="selected" value="auto">Detect language</option>
<option value="nl">Dutch</option>
<option value="en">English</option>
<option value="et">Estonian</option>
<option value="tl">Filipino</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="gl">Galician</option>
<option value="ka">Georgian</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="ht">Haitian Creole</option>
<option value="iw">Hebrew</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="id">Indonesian</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lv">Latvian</option>
<option value="lt">Lithuanian</option>
<option value="mk">Macedonian</option>
<option value="ms">Malay</option>
<option value="mt">Maltese</option>
<option value="no">Norwegian</option>
<option value="fa">Persian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sw">Swahili</option>
<option value="sv">Swedish</option>
<option value="th">Thai</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="ur">Urdu</option>
<option value="vi">Vietnamese</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
<p><span style="font-weight: bold; cursor: pointer; color: #d3d3d3;">⇄</span></p>
<select>
<option value="af">Afrikaans</option>
<option value="sq">Albanian</option>
<option value="ar">Arabic</option>
<option value="hy">Armenian</option>
<option value="az">Azerbaijani</option>
<option value="eu">Basque</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh-CN">Chinese (Simplified)</option>
<option value="zh-TW">Chinese (Traditional)</option>
<option value="hr">Croatian</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option selected="selected" value="en">English</option>
<option value="et">Estonian</option>
<option value="tl">Filipino</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="gl">Galician</option>
<option value="ka">Georgian</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="ht">Haitian Creole</option>
<option value="iw">Hebrew</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="id">Indonesian</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lv">Latvian</option>
<option value="lt">Lithuanian</option>
<option value="mk">Macedonian</option>
<option value="ms">Malay</option>
<option value="mt">Maltese</option>
<option value="no">Norwegian</option>
<option value="fa">Persian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sw">Swahili</option>
<option value="sv">Swedish</option>
<option value="th">Thai</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="ur">Urdu</option>
<option value="vi">Vietnamese</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
<div style="text-align: left; background-color: #ebeff9;">English (auto-detected) » English</div>
</div>
<div style="display: none; position: fixed; max-height: 126px; width: 450px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 2px; border-left-width: 2px; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 5px; background-color: #ffffff; overflow-x: auto; overflow-y: auto; min-height: 200px; z-index: 2147479936; text-align: center; color: #000000; right: 0px; top: 0px; border-color: #808080; border-style: dashed; padding: 3px;"><textarea style="height: 80px; width: 444px; padding: 2px; border: 1px solid rgba(7, 0, 0, 0);"></textarea>&nbsp;</p>
<select>
<option value="af">Afrikaans</option>
<option value="sq">Albanian</option>
<option value="ar">Arabic</option>
<option value="hy">Armenian</option>
<option value="az">Azerbaijani</option>
<option value="eu">Basque</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh-CN">Chinese (Simplified)</option>
<option value="zh-TW">Chinese (Traditional)</option>
<option value="hr">Croatian</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option selected="selected" value="auto">Detect language</option>
<option value="nl">Dutch</option>
<option value="en">English</option>
<option value="et">Estonian</option>
<option value="tl">Filipino</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="gl">Galician</option>
<option value="ka">Georgian</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="ht">Haitian Creole</option>
<option value="iw">Hebrew</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="id">Indonesian</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lv">Latvian</option>
<option value="lt">Lithuanian</option>
<option value="mk">Macedonian</option>
<option value="ms">Malay</option>
<option value="mt">Maltese</option>
<option value="no">Norwegian</option>
<option value="fa">Persian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sw">Swahili</option>
<option value="sv">Swedish</option>
<option value="th">Thai</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="ur">Urdu</option>
<option value="vi">Vietnamese</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
<p><span style="font-weight: bold; cursor: pointer; color: #d3d3d3;">⇄</span></p>
<select>
<option value="af">Afrikaans</option>
<option value="sq">Albanian</option>
<option value="ar">Arabic</option>
<option value="hy">Armenian</option>
<option value="az">Azerbaijani</option>
<option value="eu">Basque</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh-CN">Chinese (Simplified)</option>
<option value="zh-TW">Chinese (Traditional)</option>
<option value="hr">Croatian</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option selected="selected" value="en">English</option>
<option value="et">Estonian</option>
<option value="tl">Filipino</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="gl">Galician</option>
<option value="ka">Georgian</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="ht">Haitian Creole</option>
<option value="iw">Hebrew</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="id">Indonesian</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lv">Latvian</option>
<option value="lt">Lithuanian</option>
<option value="mk">Macedonian</option>
<option value="ms">Malay</option>
<option value="mt">Maltese</option>
<option value="no">Norwegian</option>
<option value="fa">Persian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sw">Swahili</option>
<option value="sv">Swedish</option>
<option value="th">Thai</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="ur">Urdu</option>
<option value="vi">Vietnamese</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
<div style="text-align: left; background-color: #ebeff9;">English (auto-detected) » English</div>
</div>
<div style="display: none; position: fixed; max-height: 161px; width: 450px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 2px; border-left-width: 2px; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 5px; background-color: #ffffff; overflow-x: auto; overflow-y: auto; min-height: 200px; z-index: 2147479936; text-align: center; color: #000000; right: 0px; top: 0px; border-color: #808080; border-style: dashed; padding: 3px;"><textarea style="height: 80px; width: 444px; padding: 2px; border: 1px solid rgba(7, 0, 0, 0);"></textarea>&nbsp;</p>
<select>
<option value="af">Afrikaans</option>
<option value="sq">Albanian</option>
<option value="ar">Arabic</option>
<option value="hy">Armenian</option>
<option value="az">Azerbaijani</option>
<option value="eu">Basque</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh-CN">Chinese (Simplified)</option>
<option value="zh-TW">Chinese (Traditional)</option>
<option value="hr">Croatian</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option selected="selected" value="auto">Detect language</option>
<option value="nl">Dutch</option>
<option value="en">English</option>
<option value="et">Estonian</option>
<option value="tl">Filipino</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="gl">Galician</option>
<option value="ka">Georgian</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="ht">Haitian Creole</option>
<option value="iw">Hebrew</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="id">Indonesian</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lv">Latvian</option>
<option value="lt">Lithuanian</option>
<option value="mk">Macedonian</option>
<option value="ms">Malay</option>
<option value="mt">Maltese</option>
<option value="no">Norwegian</option>
<option value="fa">Persian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sw">Swahili</option>
<option value="sv">Swedish</option>
<option value="th">Thai</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="ur">Urdu</option>
<option value="vi">Vietnamese</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
<p><span style="font-weight: bold; cursor: pointer; color: #d3d3d3;">⇄</span></p>
<select>
<option value="af">Afrikaans</option>
<option value="sq">Albanian</option>
<option value="ar">Arabic</option>
<option value="hy">Armenian</option>
<option value="az">Azerbaijani</option>
<option value="eu">Basque</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh-CN">Chinese (Simplified)</option>
<option value="zh-TW">Chinese (Traditional)</option>
<option value="hr">Croatian</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option selected="selected" value="en">English</option>
<option value="et">Estonian</option>
<option value="tl">Filipino</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="gl">Galician</option>
<option value="ka">Georgian</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="ht">Haitian Creole</option>
<option value="iw">Hebrew</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="id">Indonesian</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lv">Latvian</option>
<option value="lt">Lithuanian</option>
<option value="mk">Macedonian</option>
<option value="ms">Malay</option>
<option value="mt">Maltese</option>
<option value="no">Norwegian</option>
<option value="fa">Persian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sw">Swahili</option>
<option value="sv">Swedish</option>
<option value="th">Thai</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="ur">Urdu</option>
<option value="vi">Vietnamese</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
<div style="text-align: left; background-color: #ebeff9;">English (auto-detected) » English</div>
</div>
<div style="display: none; position: fixed; max-height: 161px; width: 450px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 2px; border-left-width: 2px; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 5px; background-color: #ffffff; overflow-x: auto; overflow-y: auto; min-height: 200px; z-index: 2147479936; text-align: center; color: #000000; right: 0px; top: 0px; border-color: #808080; border-style: dashed; padding: 3px;"><textarea style="height: 80px; width: 444px; padding: 2px; border: 1px solid rgba(7, 0, 0, 0);"></textarea></p>
<select>
<option value="af">Afrikaans</option>
<option value="sq">Albanian</option>
<option value="ar">Arabic</option>
<option value="hy">Armenian</option>
<option value="az">Azerbaijani</option>
<option value="eu">Basque</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh-CN">Chinese (Simplified)</option>
<option value="zh-TW">Chinese (Traditional)</option>
<option value="hr">Croatian</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option selected="selected" value="auto">Detect language</option>
<option value="nl">Dutch</option>
<option value="en">English</option>
<option value="et">Estonian</option>
<option value="tl">Filipino</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="gl">Galician</option>
<option value="ka">Georgian</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="ht">Haitian Creole</option>
<option value="iw">Hebrew</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="id">Indonesian</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lv">Latvian</option>
<option value="lt">Lithuanian</option>
<option value="mk">Macedonian</option>
<option value="ms">Malay</option>
<option value="mt">Maltese</option>
<option value="no">Norwegian</option>
<option value="fa">Persian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sw">Swahili</option>
<option value="sv">Swedish</option>
<option value="th">Thai</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="ur">Urdu</option>
<option value="vi">Vietnamese</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
<p><span style="font-weight: bold; cursor: pointer; color: #d3d3d3;">⇄</span></p>
<select>
<option value="af">Afrikaans</option>
<option value="sq">Albanian</option>
<option value="ar">Arabic</option>
<option value="hy">Armenian</option>
<option value="az">Azerbaijani</option>
<option value="eu">Basque</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh-CN">Chinese (Simplified)</option>
<option value="zh-TW">Chinese (Traditional)</option>
<option value="hr">Croatian</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option selected="selected" value="en">English</option>
<option value="et">Estonian</option>
<option value="tl">Filipino</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="gl">Galician</option>
<option value="ka">Georgian</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="ht">Haitian Creole</option>
<option value="iw">Hebrew</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="id">Indonesian</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lv">Latvian</option>
<option value="lt">Lithuanian</option>
<option value="mk">Macedonian</option>
<option value="ms">Malay</option>
<option value="mt">Maltese</option>
<option value="no">Norwegian</option>
<option value="fa">Persian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sw">Swahili</option>
<option value="sv">Swedish</option>
<option value="th">Thai</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="ur">Urdu</option>
<option value="vi">Vietnamese</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
<div style="text-align: left; background-color: #ebeff9;">English (auto-detected) » English</div>
</div>
<div style="display: none; position: fixed; max-height: 111px; width: 450px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 2px; border-left-width: 2px; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 5px; background-color: #ffffff; overflow-x: auto; overflow-y: auto; min-height: 200px; z-index: 2147479936; text-align: center; color: #000000; right: 0px; top: 0px; border-color: #808080; border-style: dashed; padding: 3px;"><textarea style="height: 80px; width: 444px; padding: 2px; border: 1px solid rgba(7, 0, 0, 0);"></textarea><br />
<select>
<option value="af">Afrikaans</option>
<option value="sq">Albanian</option>
<option value="ar">Arabic</option>
<option value="hy">Armenian</option>
<option value="az">Azerbaijani</option>
<option value="eu">Basque</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh-CN">Chinese (Simplified)</option>
<option value="zh-TW">Chinese (Traditional)</option>
<option value="hr">Croatian</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option selected="selected" value="auto">Detect language</option>
<option value="nl">Dutch</option>
<option value="en">English</option>
<option value="et">Estonian</option>
<option value="tl">Filipino</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="gl">Galician</option>
<option value="ka">Georgian</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="ht">Haitian Creole</option>
<option value="iw">Hebrew</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="id">Indonesian</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lv">Latvian</option>
<option value="lt">Lithuanian</option>
<option value="mk">Macedonian</option>
<option value="ms">Malay</option>
<option value="mt">Maltese</option>
<option value="no">Norwegian</option>
<option value="fa">Persian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sw">Swahili</option>
<option value="sv">Swedish</option>
<option value="th">Thai</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="ur">Urdu</option>
<option value="vi">Vietnamese</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
<p><span style="font-weight: bold; cursor: pointer; color: #d3d3d3;">⇄</span><br />
<select>
<option value="af">Afrikaans</option>
<option value="sq">Albanian</option>
<option value="ar">Arabic</option>
<option value="hy">Armenian</option>
<option value="az">Azerbaijani</option>
<option value="eu">Basque</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh-CN">Chinese (Simplified)</option>
<option value="zh-TW">Chinese (Traditional)</option>
<option value="hr">Croatian</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option selected="selected" value="en">English</option>
<option value="et">Estonian</option>
<option value="tl">Filipino</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="gl">Galician</option>
<option value="ka">Georgian</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="ht">Haitian Creole</option>
<option value="iw">Hebrew</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="id">Indonesian</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lv">Latvian</option>
<option value="lt">Lithuanian</option>
<option value="mk">Macedonian</option>
<option value="ms">Malay</option>
<option value="mt">Maltese</option>
<option value="no">Norwegian</option>
<option value="fa">Persian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sw">Swahili</option>
<option value="sv">Swedish</option>
<option value="th">Thai</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="ur">Urdu</option>
<option value="vi">Vietnamese</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
<div style="text-align: left; background-color: #ebeff9;">English (auto-detected) » English</div>
<div style="width: 444px; max-width: 444px; min-height: 80px; background-color: #ffffff; text-align: justify; padding: 2px; border: 1px solid #808080;"></div>
</div>

<p><a href="http://feedads.g.doubleclick.net/~a/QMg1Sa0H9ZAMzTN0EVxm5Rdp5-I/0/da"><img src="http://feedads.g.doubleclick.net/~a/QMg1Sa0H9ZAMzTN0EVxm5Rdp5-I/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/QMg1Sa0H9ZAMzTN0EVxm5Rdp5-I/1/da"><img src="http://feedads.g.doubleclick.net/~a/QMg1Sa0H9ZAMzTN0EVxm5Rdp5-I/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/perused/~4/VMNR9xbYmMo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.jeroenpelgrims.be/2011/03/bulktts-text-to-speech-using-google-translate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.jeroenpelgrims.be/2011/03/bulktts-text-to-speech-using-google-translate/</feedburner:origLink></item>
		<item>
		<title>Python in-memory zip file</title>
		<link>http://feedproxy.google.com/~r/perused/~3/45pers_wfZ8/</link>
		<comments>http://blog.jeroenpelgrims.be/2011/03/python-in-memory-zip-file/#comments</comments>
		<pubDate>Sun, 06 Mar 2011 11:16:28 +0000</pubDate>
		<dc:creator>Jeroen</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.jeroenpelgrims.be/?p=500</guid>
		<description><![CDATA[I needed this for something where I wanted to send the visitor of a website a bunch of files he selected at once. An easy way to do this would be to add the files to a zip file and then send that zip file to the user. Unfortunately Python doesn&#8217;t have an in-memory zip [...]]]></description>
			<content:encoded><![CDATA[<p>I needed this for something where I wanted to send the visitor of a website a bunch of files he selected at once.<br />
An easy way to do this would be to add the files to a zip file and then send that zip file to the user.<br />
Unfortunately Python doesn&#8217;t have an in-memory zip file library, you can only interact with zip files on disk.</p>
<p>After a bit of googling around I came to this <a href="http://stackoverflow.com/questions/3610221/how-to-create-an-in-memory-zip-file-with-directories-without-touching-the-disk/3616796#3616796">StackOverflow answer</a>.<br />
That worked like a charm, and here is my more reusable version:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">zipfile</span> <span style="color: #ff7700;font-weight:bold;">import</span> ZipFile
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">StringIO</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">StringIO</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> InMemoryZipFile<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
	<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
		<span style="color: #008000;">self</span>.<span style="color: black;">inMemoryOutputFile</span> = <span style="color: #dc143c;">StringIO</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> write<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, inzipfilename, data<span style="color: black;">&#41;</span>:
		<span style="color: #008000;">zip</span> = ZipFile<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">inMemoryOutputFile</span>, <span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span>
		<span style="color: #008000;">zip</span>.<span style="color: black;">writestr</span><span style="color: black;">&#40;</span>inzipfilename, data<span style="color: black;">&#41;</span>
		<span style="color: #008000;">zip</span>.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> read<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
		<span style="color: #008000;">self</span>.<span style="color: black;">inMemoryOutputFile</span>.<span style="color: black;">seek</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">inMemoryOutputFile</span>.<span style="color: black;">getvalue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> writetofile<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, filename<span style="color: black;">&#41;</span>:
		<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'out.zip'</span>, <span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Save as &#8220;inmemoryzip.py&#8221; and import it as &#8220;inmemoryzip&#8221;.<br />
This is quite limited compared to the standard ZipFile class, but this gets the job done for what I needed it.</p>
<div style="display: none; position: fixed; max-height: 517px; width: 450px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 2px; border-left-width: 2px; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 5px; background-color: #ffffff; overflow-x: auto; overflow-y: auto; min-height: 200px; z-index: 2147479936; text-align: center; color: #000000; right: 0px; top: 0px; border-color: #808080; border-style: dashed; padding: 3px;"><textarea style="height: 80px; width: 444px; padding: 2px; border: 1px solid rgba(7, 0, 0, 0);"></textarea><br />
<select>
<option value="af">Afrikaans</option>
<option value="sq">Albanian</option>
<option value="ar">Arabic</option>
<option value="hy">Armenian</option>
<option value="az">Azerbaijani</option>
<option value="eu">Basque</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh-CN">Chinese (Simplified)</option>
<option value="zh-TW">Chinese (Traditional)</option>
<option value="hr">Croatian</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option selected="selected" value="auto">Detect language</option>
<option value="nl">Dutch</option>
<option value="en">English</option>
<option value="et">Estonian</option>
<option value="tl">Filipino</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="gl">Galician</option>
<option value="ka">Georgian</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="ht">Haitian Creole</option>
<option value="iw">Hebrew</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="id">Indonesian</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lv">Latvian</option>
<option value="lt">Lithuanian</option>
<option value="mk">Macedonian</option>
<option value="ms">Malay</option>
<option value="mt">Maltese</option>
<option value="no">Norwegian</option>
<option value="fa">Persian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sw">Swahili</option>
<option value="sv">Swedish</option>
<option value="th">Thai</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="ur">Urdu</option>
<option value="vi">Vietnamese</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
<p><span style="font-weight: bold; cursor: pointer; color: #d3d3d3;">⇄</span><br />
<select>
<option value="af">Afrikaans</option>
<option value="sq">Albanian</option>
<option value="ar">Arabic</option>
<option value="hy">Armenian</option>
<option value="az">Azerbaijani</option>
<option value="eu">Basque</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh-CN">Chinese (Simplified)</option>
<option value="zh-TW">Chinese (Traditional)</option>
<option value="hr">Croatian</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option selected="selected" value="en">English</option>
<option value="et">Estonian</option>
<option value="tl">Filipino</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="gl">Galician</option>
<option value="ka">Georgian</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="ht">Haitian Creole</option>
<option value="iw">Hebrew</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="id">Indonesian</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lv">Latvian</option>
<option value="lt">Lithuanian</option>
<option value="mk">Macedonian</option>
<option value="ms">Malay</option>
<option value="mt">Maltese</option>
<option value="no">Norwegian</option>
<option value="fa">Persian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sr">Serbian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sw">Swahili</option>
<option value="sv">Swedish</option>
<option value="th">Thai</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="ur">Urdu</option>
<option value="vi">Vietnamese</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
<div style="text-align: left; background-color: #ebeff9;">English (auto-detected) » English</div>
<div style="width: 444px; max-width: 444px; min-height: 80px; background-color: #ffffff; text-align: justify; padding: 2px; border: 1px solid #808080;"></div>
</div>

<p><a href="http://feedads.g.doubleclick.net/~a/WF3VwBkFqpNnMv0xjF5cWjUm6VM/0/da"><img src="http://feedads.g.doubleclick.net/~a/WF3VwBkFqpNnMv0xjF5cWjUm6VM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/WF3VwBkFqpNnMv0xjF5cWjUm6VM/1/da"><img src="http://feedads.g.doubleclick.net/~a/WF3VwBkFqpNnMv0xjF5cWjUm6VM/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/perused/~4/45pers_wfZ8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.jeroenpelgrims.be/2011/03/python-in-memory-zip-file/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.jeroenpelgrims.be/2011/03/python-in-memory-zip-file/</feedburner:origLink></item>
		<item>
		<title>Solving 8 Queens problem on an 8×8 board with a Genetic Algorithm.</title>
		<link>http://feedproxy.google.com/~r/perused/~3/Pxdt5HjayJY/</link>
		<comments>http://blog.jeroenpelgrims.be/2011/01/solving-8-queens-problem-on-an-8x8-board-with-a-genetic-algorithm/#comments</comments>
		<pubDate>Thu, 20 Jan 2011 00:55:12 +0000</pubDate>
		<dc:creator>Jeroen</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[School]]></category>

		<guid isPermaLink="false">http://blog.jeroenpelgrims.be/?p=470</guid>
		<description><![CDATA[I have an Artificial Intelligence course and one type of search algorithm handled is Genetic Algorithms. Very interesting because it uses the principle of evolution to find a solution to a problem. You start with a population of begin states and each state has a &#8216;fitness&#8217; which indicates how close it is to a solution. [...]]]></description>
			<content:encoded><![CDATA[<p>I have an Artificial Intelligence course and one type of search algorithm handled is Genetic Algorithms.<br />
Very interesting because it uses the principle of evolution to find a solution to a problem.</p>
<p>You start with a population of begin states and each state has a &#8216;fitness&#8217; which indicates how close it is to a solution.<br />
Based on that fitness you will crossjoin or mate 2 states. Higher fitness = higher chance of mating.</p>
<p>I implemented the example given in my AI course&#8217;s slides in python.<br />
The example is trying to find a solution to solve an <a href="http://en.wikipedia.org/wiki/N-queens">n-queens problem</a>, in this case 8 queens on an 8&#215;8 chessboard.<br />
Briefly explained: you need to place 8 queens on a chessboard so that none of the queens can attack eachother.<br />
(A queen can move like a Bishop and a Tower, horizontally and diagonally)</p>
<p><span id="more-470"></span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">__future__</span> <span style="color: #ff7700;font-weight:bold;">import</span> division
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">random</span> <span style="color: #ff7700;font-weight:bold;">import</span> Random, <span style="color: #dc143c;">random</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> State<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
	MUTATION_RATE = <span style="color: #ff4500;">0.03</span>
	<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parents=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
		r = Random<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		<span style="color: #008000;">self</span>._fitness = <span style="color: #008000;">None</span>
		<span style="color: #008000;">self</span>._probability = <span style="color: #008000;">None</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> parents==<span style="color: #008000;">None</span>:
			<span style="color: #008000;">self</span>.<span style="color: black;">state</span> = <span style="color: black;">&#91;</span>r.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> y <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
		<span style="color: #ff7700;font-weight:bold;">else</span>:
			parent1 = parents<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
			parent2 = parents<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
			<span style="color: #008000;">self</span>.<span style="color: black;">state</span> = <span style="color: #008000;">self</span>.<span style="color: black;">crossover</span><span style="color: black;">&#40;</span>parent1, parent2<span style="color: black;">&#41;</span>
			<span style="color: #008000;">self</span>.<span style="color: black;">mutate</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> fitness<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>._fitness:
			state = <span style="color: #008000;">self</span>.<span style="color: black;">state</span>
			horizontal_collisions = <span style="color: #008000;">sum</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>state.<span style="color: black;">count</span><span style="color: black;">&#40;</span>col<span style="color: black;">&#41;</span>-<span style="color: #ff4500;">1</span> <span style="color: #ff7700;font-weight:bold;">for</span> col <span style="color: #ff7700;font-weight:bold;">in</span> state<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>/<span style="color: #ff4500;">2</span>
&nbsp;
			diagonal_collisions = <span style="color: #ff4500;">0</span>
			<span style="color: #ff7700;font-weight:bold;">for</span> i, col <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span>state<span style="color: black;">&#41;</span>:
				<span style="color: #ff7700;font-weight:bold;">for</span> j, diagonal <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span>state<span style="color: black;">&#41;</span>:
					mod = <span style="color: #008000;">abs</span><span style="color: black;">&#40;</span>i-j<span style="color: black;">&#41;</span>
					<span style="color: #ff7700;font-weight:bold;">if</span> mod <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">0</span>: <span style="color: #808080; font-style: italic;">#we don't want to count the current queen in a collision with herself</span>
						<span style="color: #ff7700;font-weight:bold;">if</span> diagonal + mod == col <span style="color: #ff7700;font-weight:bold;">or</span> diagonal - mod == col:
							diagonal_collisions += <span style="color: #ff4500;">1</span>
			diagonal_collisions /= <span style="color: #ff4500;">2</span> <span style="color: #808080; font-style: italic;">#we were counting the diagonal collisions double</span>
			<span style="color: #008000;">self</span>._fitness = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">28</span> - <span style="color: black;">&#40;</span>horizontal_collisions + diagonal_collisions<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._fitness
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> probability<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, population<span style="color: black;">&#41;</span>:
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>._probability:
			<span style="color: #008000;">self</span>._probability = <span style="color: #008000;">self</span>.<span style="color: black;">fitness</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> / <span style="color: #008000;">sum</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>x.<span style="color: black;">fitness</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> population<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._probability
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> crossover<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent1, parent2<span style="color: black;">&#41;</span>:
		r = Random<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		crossover_index = r.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span>
		left = parent1.<span style="color: black;">state</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>:crossover_index<span style="color: black;">&#93;</span>
		right = parent2.<span style="color: black;">state</span><span style="color: black;">&#91;</span>crossover_index:<span style="color: #ff4500;">8</span><span style="color: black;">&#93;</span>
		left.<span style="color: black;">extend</span><span style="color: black;">&#40;</span>right<span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">return</span> left
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> mutate<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
		r = Random<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">state</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
			<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">random</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> State.<span style="color: black;">MUTATION_RATE</span>:
				<span style="color: #008000;">self</span>.<span style="color: black;">state</span><span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span> = r.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__str__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
		r = <span style="color: #483d8b;">''</span>
		r += <span style="color: #483d8b;">'   '</span>
		<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span>:
			r += <span style="color: #483d8b;">'%d '</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>i+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
		r += <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>  '</span> + <span style="color: #483d8b;">'--'</span><span style="color: #66cc66;">*</span><span style="color: #ff4500;">8</span> + <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">8</span>,<span style="color: #ff4500;">0</span>,-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:
			r += <span style="color: #483d8b;">'%d|'</span> <span style="color: #66cc66;">%</span> i
			<span style="color: #ff7700;font-weight:bold;">for</span> j, queen <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">state</span><span style="color: black;">&#41;</span>:
				<span style="color: #ff7700;font-weight:bold;">if</span> queen == i:
					r += <span style="color: #483d8b;">' O'</span>
				<span style="color: #ff7700;font-weight:bold;">else</span>:
					r += <span style="color: #483d8b;">'  '</span>
			r += <span style="color: #483d8b;">'|<span style="color: #000099; font-weight: bold;">\n</span>'</span>
		r += <span style="color: #483d8b;">'  '</span> + <span style="color: #483d8b;">'--'</span><span style="color: #66cc66;">*</span><span style="color: #ff4500;">8</span> + <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>
		<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">self</span>.<span style="color: black;">fitness</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">return</span> r
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> pickRandomByProbability<span style="color: black;">&#40;</span>populationByProbability<span style="color: black;">&#41;</span>:
	i = <span style="color: #ff4500;">0</span>
	selectedState = <span style="color: #008000;">None</span>
	<span style="color: #ff7700;font-weight:bold;">while</span> selectedState == <span style="color: #008000;">None</span>:
		current = populationByProbability<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> current<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">&lt;</span>= <span style="color: #dc143c;">random</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
 			<span style="color: #ff7700;font-weight:bold;">return</span> current<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
 		<span style="color: #ff7700;font-weight:bold;">if</span> i+<span style="color: #ff4500;">1</span> <span style="color: #66cc66;">&gt;</span>= <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>populationByProbability<span style="color: black;">&#41;</span>:
			i = <span style="color: #ff4500;">0</span>
		<span style="color: #ff7700;font-weight:bold;">else</span>:
			i += <span style="color: #ff4500;">1</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> generateNextPopulation<span style="color: black;">&#40;</span>population, n<span style="color: black;">&#41;</span>:
	newPopulation = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
	<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>newPopulation<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> n:
 		populationByProbability = <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>x.<span style="color: black;">probability</span><span style="color: black;">&#40;</span>population<span style="color: black;">&#41;</span>, x<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> population<span style="color: black;">&#93;</span>
 		parent1 = pickRandomByProbability<span style="color: black;">&#40;</span>populationByProbability<span style="color: black;">&#41;</span>
 		populationByProbability = <span style="color: black;">&#91;</span>x <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> populationByProbability <span style="color: #ff7700;font-weight:bold;">if</span> x<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">!</span>= parent1<span style="color: black;">&#93;</span>
 		parent2 = pickRandomByProbability<span style="color: black;">&#40;</span>populationByProbability<span style="color: black;">&#41;</span>
 		newPopulation.<span style="color: black;">append</span><span style="color: black;">&#40;</span>State<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>parent1, parent2<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
 	<span style="color: #ff7700;font-weight:bold;">return</span> newPopulation
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
 	populationSize = <span style="color: #ff4500;">100</span>
 	generation = <span style="color: #ff4500;">1</span>
 	population = <span style="color: black;">&#91;</span>State<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>populationSize<span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
 	<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff4500;">28</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span>x.<span style="color: black;">fitness</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> population<span style="color: black;">&#93;</span>:
 		<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;generation %d<span style="color: #000099; font-weight: bold;">\t</span>Max fitness: %d&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>generation, <span style="color: #008000;">max</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>x.<span style="color: black;">fitness</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> population<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
 		population = generateNextPopulation<span style="color: black;">&#40;</span>population, populationSize<span style="color: black;">&#41;</span>
 		generation += <span style="color: #ff4500;">1</span>
 	<span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> population:
 		<span style="color: #ff7700;font-weight:bold;">if</span> x.<span style="color: black;">fitness</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span>= <span style="color: #ff4500;">28</span>:
			<span style="color: #ff7700;font-weight:bold;">print</span> x</pre></td></tr></table></div>

<h3>State</h3>
<p>The State class keeps track of a state. In this case that is a list of 8 integers ranging from 1 to 8.<br />
Each integer represents the position of a queen in a column (which row).<br />
Since queens can attack vertically each queen has to be in a different column by default.</p>
<h3>Fitness</h3>
<p>A collision is two queens who are able to attack each other. This means they are in the same diagonal, the same row or the same column.<br />
The maximum amount of collisions that can occur is 28. The fitness function is a higher-is-better function, so we calculate it by substracting the amount of collisions that occur in the current state from 28.<br />
A solution would have 0 collisions and thus a fitness of 28.</p>
<h3>Probability of mating</h3>
<p>When we generate the next population of states we will need to have something on which we can base which 2 states can &#8216;mate&#8217;.<br />
We want only the best states (the one closest to a solution) to mate, so the best heuristic to define the chance of a state being allowed to mate is it&#8217;s fitness.</p>
<h3>Crossover (mating), mutation</h3>
<p>When we crossover 2 states we choose a point in the states where we will &#8216;chop&#8217; them in 2 parts.<br />
We will for example take the left 3 columns of the 1st parent and the 5 last of the second parent.<br />
The child state is then the combination of these columns.<br />
We don&#8217;t want to stay stuck in the same state pool because what if the initially randomly generated population has no queen in row 3?<br />
We would never be able to get a solution because a solution requires a queen in each row.<br />
No matter how many times we crossover 2 states, we will never get a state in row 3.<br />
Therefore we need to include a random mutation when crossing over 2 parents.<br />
Each column in the child state has a specific percentage chance of changing it&#8217;s value to a random number from 1 to 8.</p>
<h3>Conclusion</h3>
<p>I&#8217;ve noticed that this doesn&#8217;t find a solution as fast as I initially expected. It can quickly take over a few (ten)thousand generations before a solution is found.<br />
I haven&#8217;t noticed any noticeable speed increase in finding a solution when taking a population of 100, 1000 or 10000. (Didn&#8217;t do any benchmarks, just a few runs per population size)<br />
Maybe a solution would be found more quickly if the percentage chance of mating weren&#8217;t on a linear scale but an exponential one.<br />
I&#8217;m not sure if i&#8217;m expressing this correctly but what I mean is that the chance of mating for bad fitnesses and good ones is currently too close. Good ones should be picked way easier than bad ones. Now the chance differs only by a few percent or even a few tenths of a percent depending on the size of the population.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/5RYmh2KSyitP1-8pdDPrnJTJyhs/0/da"><img src="http://feedads.g.doubleclick.net/~a/5RYmh2KSyitP1-8pdDPrnJTJyhs/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/5RYmh2KSyitP1-8pdDPrnJTJyhs/1/da"><img src="http://feedads.g.doubleclick.net/~a/5RYmh2KSyitP1-8pdDPrnJTJyhs/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/perused/~4/Pxdt5HjayJY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.jeroenpelgrims.be/2011/01/solving-8-queens-problem-on-an-8x8-board-with-a-genetic-algorithm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.jeroenpelgrims.be/2011/01/solving-8-queens-problem-on-an-8x8-board-with-a-genetic-algorithm/</feedburner:origLink></item>
		<item>
		<title>Django on Google App Engine – 2</title>
		<link>http://feedproxy.google.com/~r/perused/~3/1Wu_4itBJL8/</link>
		<comments>http://blog.jeroenpelgrims.be/2011/01/django-on-google-app-engine-2/#comments</comments>
		<pubDate>Sun, 09 Jan 2011 18:58:25 +0000</pubDate>
		<dc:creator>Jeroen</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.jeroenpelgrims.be/?p=451</guid>
		<description><![CDATA[The previous post was about the basics of setting up an application using Django on Google App Engine. This one will continue on that as we follow the Django Tutorial for building a poll application, but with some modifications so it will run on GAE. Setting some settings First of all, set your application id [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://blog.jeroenpelgrims.be/2011/01/django-on-google-app-engine-1/">previous post</a> was about the basics of setting up an application using Django on Google App Engine.<br />
This one will continue on that as we follow the <a href="http://docs.djangoproject.com/en/1.2/intro/tutorial01/">Django Tutorial</a> for building a poll application, but with some modifications so it will run on GAE.</p>
<p><span id="more-451"></span></p>
<h3>Setting some settings</h3>
<p>First of all, set your application id to whatever you called your application in the GAE dashboard.<br />
Open up app.yaml in the root folder and change what&#8217;s behind &#8220;application: &#8220;.<br />
This isn&#8217;t a requirement to be able to develop for GAE, but if you want to deploy your app this will need to be set.</p>
<p>Open up settings.py. If you want to use sessions in your application you&#8217;ll need to uncomment &#8220;django.contrib.sessions.middleware.SessionMiddleware&#8221; in MIDDLEWARE_CLASSES near the end of the file.</p>
<p>If you&#8217;re planning on using GAE&#8217;s memcache you&#8217;ll need to add the following lines to MIDDLEWARE_CLASSES:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">'django.middleware.cache.UpdateCacheMiddleware'</span>,
<span style="color: #483d8b;">'django.middleware.common.CommonMiddleware'</span>,
<span style="color: #483d8b;">'django.middleware.cache.FetchFromCacheMiddleware'</span>,</pre></div></div>

<p>And you&#8217;ll need to set these variables as well:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">CACHE_BACKEND = <span style="color: #483d8b;">'memcached://?timeout=0'</span>
CACHE_MIDDLEWARE_SECONDS = <span style="color: #ff4500;">0</span></pre></div></div>

<p>CACHE_MIDDLEWARE_SECONDS sets the default caching time in seconds for each page. Since I don&#8217;t want every page to be cached by default I&#8217;ve set this value to 0.<br />
Note that the setting of the cache info is different in Django 1.3. (I&#8217;m using 1.2.4 here)</p>
<p>Then at the bottom in INSTALLED_APPS add a line with the name of the app we&#8217;ll be creating.<br />
In the tutorial they&#8217;re using the name &#8220;polls&#8221;, so that&#8217;s what i&#8217;ll call it as well.</p>
<p><a href="http://blog.jeroenpelgrims.be/wp-content/uploads/2011/01/settings.txt">This</a> is how my settings file looks now.<br />
And that&#8217;s all the settings that we need to set. The database (Google&#8217;s BigTable) settings have already been taken care of by the helper.</p>
<h3>Creating the application and creating models</h3>
<p>Open a command prompt and cd to where manage.py is situated. (in the root folder of the project)<br />
Type &#8220;python manage.py startapp polls&#8221;. or replace polls by whatever name you set in INSTALLED_APPS.</p>
<p>The models we&#8217;ll be creating won&#8217;t extend from the standard Django base model but instead will use the base class provided by the helper. This is an edited version of the Django base model class that is compatible with the GAE datastore.</p>
<p>models.py:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> appengine_django.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> BaseModel
<span style="color: #ff7700;font-weight:bold;">from</span> google.<span style="color: black;">appengine</span>.<span style="color: black;">ext</span> <span style="color: #ff7700;font-weight:bold;">import</span> db
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Poll<span style="color: black;">&#40;</span>BaseModel<span style="color: black;">&#41;</span>:
    question = db.<span style="color: black;">StringProperty</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    pubDate = db.<span style="color: black;">DateTimeProperty</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Choice<span style="color: black;">&#40;</span>BaseModel<span style="color: black;">&#41;</span>:
    pollId = db.<span style="color: black;">IntegerProperty</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    choice = db.<span style="color: black;">StringProperty</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    votes = db.<span style="color: black;">IntegerProperty</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Notice that there are no foreign keys, this is because GAE is a non-relational data store. Foreign keys don&#8217;t exist.</p>
<h3>Views and templates</h3>
<p>We&#8217;ll need 3 pages:</p>
<ol>
<li>Create  a poll</li>
<li>List existing polls</li>
<li>View a specific poll and be able to vote on one of it&#8217;s choices</li>
</ol>
<p>My urls.py file is as follows:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span>.<span style="color: black;">urls</span>.<span style="color: black;">defaults</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
urlpatterns = patterns<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>,
	<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^$'</span>, r<span style="color: #483d8b;">'polls.views.list'</span><span style="color: black;">&#41;</span>,
	<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^create$'</span>, r<span style="color: #483d8b;">'polls.views.create'</span><span style="color: black;">&#41;</span>,
	<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^view/(<span style="color: #000099; font-weight: bold;">\d</span>+)$'</span>, r<span style="color: #483d8b;">'polls.views.view'</span><span style="color: black;">&#41;</span>,
<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h4>The views:</h4>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">shortcuts</span> <span style="color: #ff7700;font-weight:bold;">import</span> render_to_response
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">http</span> <span style="color: #ff7700;font-weight:bold;">import</span> HttpResponse, HttpResponseRedirect
<span style="color: #ff7700;font-weight:bold;">from</span> polls.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> Poll, Choice
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> create<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
	<span style="color: #ff7700;font-weight:bold;">if</span> request.<span style="color: black;">POST</span>:
		question = request.<span style="color: black;">POST</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;question&quot;</span><span style="color: black;">&#93;</span>
		c1 = request.<span style="color: black;">POST</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;choice1&quot;</span><span style="color: black;">&#93;</span>
		c2 = request.<span style="color: black;">POST</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;choice2&quot;</span><span style="color: black;">&#93;</span>
		c3 = request.<span style="color: black;">POST</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;choice3&quot;</span><span style="color: black;">&#93;</span>
&nbsp;
		poll = Poll<span style="color: black;">&#40;</span>question=question, pubDate=<span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
		poll.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		choice1 = Choice<span style="color: black;">&#40;</span>pollId=poll.<span style="color: black;">key</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, choice=c1, votes=<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
		choice2 = Choice<span style="color: black;">&#40;</span>pollId=poll.<span style="color: black;">key</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, choice=c2, votes=<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
		choice3 = Choice<span style="color: black;">&#40;</span>pollId=poll.<span style="color: black;">key</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, choice=c3, votes=<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
		choice1.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		choice2.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		choice3.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">return</span> HttpResponseRedirect<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">else</span>:
		<span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'create.html'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
	polls = Poll.<span style="color: black;">objects</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'list.html'</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">'polls'</span>:polls<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> view<span style="color: black;">&#40;</span>request, <span style="color: #008000;">id</span><span style="color: black;">&#41;</span>:
	<span style="color: #ff7700;font-weight:bold;">if</span> request.<span style="color: black;">POST</span>:
		choiceId = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>request.<span style="color: black;">POST</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;voteChoice&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
		choice = Choice.<span style="color: black;">get_by_id</span><span style="color: black;">&#40;</span>choiceId<span style="color: black;">&#41;</span>
		choice.<span style="color: black;">votes</span> += <span style="color: #ff4500;">1</span>
		choice.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
	<span style="color: #008000;">id</span> = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #008000;">id</span><span style="color: black;">&#41;</span>
	poll = Poll.<span style="color: black;">get_by_id</span><span style="color: black;">&#40;</span><span style="color: #008000;">id</span><span style="color: black;">&#41;</span>
	choices = Choice.<span style="color: black;">objects</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'pollId ='</span>, <span style="color: #008000;">id</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'view.html'</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">'poll'</span>:poll, <span style="color: #483d8b;">'choices'</span>:choices<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h4>The templates:</h4>
<p>list.html</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;ul&gt;
 {% for poll in polls %}
 &lt;li&gt;
 &lt;a href=&quot;/view/{{poll.key.id}}&quot;&gt;{{poll.question}}&lt;/a&gt; - {{poll.pubDate}}
 &lt;/li&gt;
 {% endfor %}
&lt;/ul&gt;
&lt;a href=&quot;/create&quot;&gt;Create new poll&lt;/a&gt;</pre></td></tr></table></div>

<p>view.html</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="html4" style="font-family:monospace;">&lt;h1&gt;{{poll.question}}&lt;/h1&gt;
&nbsp;
&lt;form action=&quot;/view/{{poll.key.id}}&quot; method=&quot;post&quot;&gt;
 &lt;ul&gt;
 {% for choice in choices %}
 &lt;li&gt;
 &lt;input name=&quot;voteChoice&quot; type=&quot;radio&quot; value=&quot;{{choice.key.id}}&quot;&gt;
 {{choice.choice}} ({{choice.votes}} votes)
 &lt;/li&gt;
 {% endfor %}
 &lt;/ul&gt;
 &lt;input type=&quot;submit&quot; value=&quot;Vote&quot; /&gt;
&lt;/form&gt;</pre></td></tr></table></div>

<p>create.html</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;h1&gt;Create poll&lt;/h1&gt;
&nbsp;
&lt;form action=&quot;/create&quot; method=&quot;post&quot;&gt;
 Question: &lt;input type=&quot;text&quot; name=&quot;question&quot; /&gt;&lt;br&gt;
&nbsp;
 Choice 1: &lt;input type=&quot;text&quot; name=&quot;choice1&quot; /&gt;&lt;br&gt;
 Choice 2: &lt;input type=&quot;text&quot; name=&quot;choice2&quot; /&gt;&lt;br&gt;
 Choice 3: &lt;input type=&quot;text&quot; name=&quot;choice3&quot; /&gt;&lt;br&gt;
&nbsp;
 &lt;input type=&quot;submit&quot; value=&quot;Create&quot; /&gt;
&lt;/form&gt;</pre></td></tr></table></div>

<p>I think everything is quite clear when you look it over.<br />
There are a few differences with regular Django code, for example the <a href="http://stackoverflow.com/questions/2920236/django-get-query-not-working/2921685#2921685">filter line</a>.</p>
<p>A zip file with the files of the project can be found <a href="http://blog.jeroenpelgrims.be/wp-content/uploads/2011/01/appengine_helper_for_django.zip">here</a>.</p>
<p><strong>Update</strong>:  You might also be interested in checking out <a href="http://www.allbuttonspressed.com/projects/djangoappengine">Django-nonrel</a> which is a different way of running Django on GAE. It seems to be more flexible at first glance than the helper but I can&#8217;t say for sure since I haven&#8217;t used it yet.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/d5bPu_tE_oCiWOtRaBs7HSpRrCw/0/da"><img src="http://feedads.g.doubleclick.net/~a/d5bPu_tE_oCiWOtRaBs7HSpRrCw/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/d5bPu_tE_oCiWOtRaBs7HSpRrCw/1/da"><img src="http://feedads.g.doubleclick.net/~a/d5bPu_tE_oCiWOtRaBs7HSpRrCw/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/perused/~4/1Wu_4itBJL8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.jeroenpelgrims.be/2011/01/django-on-google-app-engine-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.jeroenpelgrims.be/2011/01/django-on-google-app-engine-2/</feedburner:origLink></item>
		<item>
		<title>Django on Google App Engine – 1</title>
		<link>http://feedproxy.google.com/~r/perused/~3/dcNu0wOKk_Q/</link>
		<comments>http://blog.jeroenpelgrims.be/2011/01/django-on-google-app-engine-%e2%80%93-1/#comments</comments>
		<pubDate>Sun, 09 Jan 2011 14:43:43 +0000</pubDate>
		<dc:creator>Jeroen</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.jeroenpelgrims.be/?p=448</guid>
		<description><![CDATA[It&#8217;s been a while since I&#8217;ve written something here, that&#8217;s cause I&#8217;ve been quite busy with school. (recreational as well as educational :)) I was planning on writing a big series of blog posts about solving the exercises in SICP as a way of studying for my exams, but as I was solving them I [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while since I&#8217;ve written something here, that&#8217;s cause I&#8217;ve been quite busy with school. (recreational as well as educational :))<br />
I was planning on writing a big series of blog posts about solving the exercises in <a href="http://mitpress.mit.edu/sicp/">SICP</a> as a way of studying for my exams, but as I was solving them I noticed there are quite a lot of them and there are a bunch of pretty hard ones in there so that didn&#8217;t quite fit in my schedule :)<br />
But I&#8217;ve made a start so I&#8217;ll probably continue it one day or an other.</p>
<p>As I was studying I naturally got bored of it, so I looked for more interesting things to do &#8211; Learn something else :D<br />
I already looked for information about setting Django up on GAE (Google App Engine) but only found information scattered on different websites/blogs/.. but I finally managed to figure it out.</p>
<p>This post should serve as a single list of instructions to follow how to get Django running on GAE.</p>
<p><span id="more-448"></span></p>
<h3>Requirements</h3>
<p>You&#8217;ll need to download a few files which we&#8217;ll need.</p>
<ol>
<li>The <a href="http://code.google.com/appengine/downloads.html">App Engine SDK</a> for Python. (1.4.1 atm)</li>
<li>Your <a href="http://www.djangoproject.com/download/">Django</a> version of choice. I&#8217;m using 1.2.4 here but it should work with everything &gt;= 1.0.</li>
<li>The <a href="http://code.google.com/p/google-app-engine-django/downloads/list">App Engine Helper for Django</a>. (r109 atm)</li>
</ol>
<p>Extract the App Engine Helper for Django somewhere.<br />
The folder is called &#8220;appengine_helper_for_django&#8221; here and contains the following important files:</p>
<ul>
<li>appengine_django/</li>
<li>app.yaml</li>
<li>main.py</li>
<li>manage.py</li>
<li>settings.py</li>
<li>urls.py</li>
<li>other information files.</li>
</ul>
<p>Most of these files have been altered so that Django can easily be run on Google App Engine.<br />
But because Google App Engine is a quite restricted platform, not all features of Django will work out of the box, or at all.<br />
One example is the Django admin module, this one is not supported.</p>
<h3>Getting it to work</h3>
<p>Now extract the Django sources somewhere else.<br />
Go to where the setup.py file is within the folder you just extracted.<br />
On the same level there should be a folder called &#8220;django&#8221;, copy this folder and paste it in the App Engine Helper folder we were in earlier.<br />
You should now have 2 folders in the helper&#8217;s folder, &#8220;appengine_django&#8221; and &#8220;django&#8221;.</p>
<p>The django folder we just copied will define which version you&#8217;ll be running on GAE.<br />
In my case, I downloaded Django 1.2.4, so I&#8217;ll be using that version on GAE.</p>
<p>Now we can try running this setup.<br />
Start up the GAE Launcher and choose file &gt; add existing application.<br />
Select the helper&#8217;s folder (where app.yaml is situated) and choose Add.<br />
Click run and click Browse after it&#8217;s done booting.<br />
You should now be able to see the Django welcome screen.</p>
<p>If you have your application if set correctly in the  app.yaml file you could just press deploy and this is what you&#8217;d be seeing on http://[your-appname].appspot.com</p>
<p>The <a href="http://blog.jeroenpelgrims.be/2011/01/django-on-google-app-engine-2/">next post</a> will handle the actual creating of a small app in Django.<br />
There are a few small and larger differences you need to take in to account.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/ce4VVAv9Ju9JlJ2stLF3ywmUHdk/0/da"><img src="http://feedads.g.doubleclick.net/~a/ce4VVAv9Ju9JlJ2stLF3ywmUHdk/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/ce4VVAv9Ju9JlJ2stLF3ywmUHdk/1/da"><img src="http://feedads.g.doubleclick.net/~a/ce4VVAv9Ju9JlJ2stLF3ywmUHdk/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/perused/~4/dcNu0wOKk_Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.jeroenpelgrims.be/2011/01/django-on-google-app-engine-%e2%80%93-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.jeroenpelgrims.be/2011/01/django-on-google-app-engine-%e2%80%93-1/</feedburner:origLink></item>
		<item>
		<title>Using C#-style Events In Python – a more Pythonic version</title>
		<link>http://feedproxy.google.com/~r/perused/~3/rCTtO26n1A0/</link>
		<comments>http://blog.jeroenpelgrims.be/2010/08/using-c-style-events-in-python-a-more-pythonic-version/#comments</comments>
		<pubDate>Sat, 28 Aug 2010 14:28:13 +0000</pubDate>
		<dc:creator>Jeroen</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.jeroenpelgrims.be/?p=276</guid>
		<description><![CDATA[I was asked by Davy how my previous code would be written in idiomatic python. First of all I had a vague recollection of what idiomatic meant but I looked it&#8217;s meaning up just to be sure. And then I had to find out how this relates to Python. Idiomatic Python? I quickly (re)discovered a [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked by Davy how my previous code would be written in idiomatic python.<br />
First of all I had a vague recollection of what idiomatic meant but I looked <a href="http://dictionary.reference.com/browse/idiomatic">it&#8217;s meaning</a> up just to be sure.<br />
And then I had to find out how this relates to Python.</p>
<p><span id="more-276"></span></p>
<h3>Idiomatic Python?</h3>
<p>I quickly (re)discovered <a href="http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html">a page</a> dedicated to giving aspiring Pythonistas guidelines to writing correct python code.<br />
Especially <a href="http://www.python.org/dev/peps/pep-0020/">The Zen of Python</a> describes more generally how to write correct Python code (not at statement level, but application/class level &#8211; more general).<br />
The first time I discovered &#8216;Code like a Pythonista&#8217; I guess the only thing I did was skim the statement level tips.</p>
<p>What Davy&#8217;s asking is more of the general kind I think though.</p>
<h3>My attempt</h3>
<pre class="brush: python; title: ; notranslate">
class Event(object):
	def __init__(self):
		self.__handlers = []

	def subscribe(self, handler):
		self.__handlers.append(handler)

	def unsubscribe(self, handler):
		self.__handlers.remove(handler)

	def __call__(self, *args):
		for handler in self.__handlers:
			handler(*args)

class Publisher(object):
	def __init__(self):
		self.notify = Event()

	def trigger_notify(self):
		self.notify(&quot;A&quot;, &quot;B&quot;)

class Subscriber(object):
	def start_listening_to(self, publisher):
		self.__publisher = publisher
		self.__publisher.notify.subscribe(self.event_handler)

	def stop_listening(self):
		self.__publisher.notify.unsubscribe(self.event_handler)
		self.__publisher = None

	def event_handler(self, param1, param2):
		print &quot;RECEIVED: param1: %s, param2: %s&quot; % (param1, param2)

publisher = Publisher()
subscriber1 = Subscriber()
subscriber2 = Subscriber()
subscriber1.start_listening_to(publisher)
subscriber2.start_listening_to(publisher)
publisher.trigger_notify()
subscriber1.stop_listening()
publisher.trigger_notify()
</pre>
<p>I removed the alteration of the object base class. It didn&#8217;t seem like the right thing to do, modifying an existing class.<br />
Now the setting of an event attribute is a lot simpler, just say that attribute x is an event.</p>
<p>I liked the way of adding and removing events by using the += and -= operators, but it didn&#8217;t seem very intuitive to me and I&#8217;ve never seen them be used like that in Python so I changed it to regular methods.</p>
<p>The way arguments are passed to the handlers also changed, I used to pass an array of arguments when calling the event.<br />
Now I just pass arguments like you would with any other function. Way more intuitive.</p>
<p>When subscribing I also don&#8217;t check whether the handler is callable anymore.<br />
When triggering the event you&#8217;ll get an appropriate error message if the handler is in fact not callable.<br />
The same happens when you pass a handler which has the incorrect amount of parameters.</p>
<h3>Checking with more experienced people</h3>
<p>After I modified the code I posted a thread on #python and on <a href="http://www.reddit.com/r/Python/d6aly/">/r/python</a> asking for some tips on further improving this code.</p>
<p>First of all, this (events) apparently already exists in <a href="http://twistedmatrix.com/trac/">twisted</a>, so when using it in a real project it might be better checking that out first.</p>
<p>I was told not to use __ to indicate attributes as private. It&#8217;s a misnomer and shows you&#8217;re still green behind the ears. A regular underscore is enough to indicate that an attribute should not be touched. I looked around and found <a href="http://stackoverflow.com/questions/70528/why-are-pythons-private-methods-not-actually-private/70900#70900">this</a> Stackoverflow answer which explains it quite nicely.</p>
<p>It was also suggested to use  *args, **kwargs instead of just *args so I can trigger the event with keyword arguments.<br />
I assumed *args would handle both named and unnamed. But that&#8217;s why I asked for tips, learn something new every day :)</p>
<p>Another thing that was suggested is to use a set or a dictionary for storing the handlers. It is apparently faster to remove handlers then and also makes sense since this way you can&#8217;t subscribe the same subscriber&#8217;s handler twice to the event.</p>
<h3>Implementing the tips</h3>
<pre class="brush: python; title: ; notranslate">
#/usr/bin/python

class Event(object):
	def __init__(self):
		self._handlers = set()

	def subscribe(self, handler):
		self._handlers.add(handler)

	def unsubscribe(self, handler):
		self._handlers.remove(handler)

	def __call__(self, *args, **kwargs):
		for handler in self._handlers:
			handler(*args, **kwargs)

class Publisher(object):
	def __init__(self):
		self.notify = Event()

	def trigger_notify(self):
		self.notify(&quot;A&quot;, param2=&quot;B&quot;, param4=&quot;C&quot;)

class Subscriber(object):
	def start_listening_to(self, publisher):
		self._publisher = publisher
		self._publisher.notify.subscribe(self.event_handler)

	def stop_listening(self):
		self._publisher.notify.unsubscribe(self.event_handler)
		self._publisher = None

	def event_handler(self, param1, param2=None, param3=None, param4=None):
		print &quot;RECEIVED: param1: %s, param2: %s, param3: %s, param4: %s&quot; % (param1, param2, param3, param4)

publisher = Publisher()
subscriber1 = Subscriber()
subscriber2 = Subscriber()
subscriber1.start_listening_to(publisher)
subscriber2.start_listening_to(publisher)
publisher.trigger_notify()
subscriber1.stop_listening()
publisher.trigger_notify()
</pre>
<p><a href="http://ideone.com/JI0m0">[run the code]</a></p>
<p>The code looks a lot cleaner and easier to use than <a href="http://blog.jeroenpelgrims.be/2010/08/using-c-style-events-in-python/">what I started out with</a> imo.</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1914px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">http://ideone.com/J3Yry</div>

<p><a href="http://feedads.g.doubleclick.net/~a/2qU8ZbmJZf_uBQpHvYv8z3iIxA8/0/da"><img src="http://feedads.g.doubleclick.net/~a/2qU8ZbmJZf_uBQpHvYv8z3iIxA8/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/2qU8ZbmJZf_uBQpHvYv8z3iIxA8/1/da"><img src="http://feedads.g.doubleclick.net/~a/2qU8ZbmJZf_uBQpHvYv8z3iIxA8/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/perused/~4/rCTtO26n1A0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.jeroenpelgrims.be/2010/08/using-c-style-events-in-python-a-more-pythonic-version/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.jeroenpelgrims.be/2010/08/using-c-style-events-in-python-a-more-pythonic-version/</feedburner:origLink></item>
	</channel>
</rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced

Served from: blog.jeroenpelgrims.be @ 2012-02-17 09:41:45 -->

