<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3748499357064620349</id><updated>2011-09-14T17:34:20.282+01:00</updated><category term='mobile'/><category term='gnuplot'/><category term='education'/><category term='technology'/><category term='cuts'/><category term='transport'/><category term='news'/><category term='web'/><category term='bugs'/><category term='books'/><category term='ucu'/><category term='apple'/><category term='tablet'/><category term='lucid'/><category term='christmas'/><category term='social'/><category term='youtube'/><category term='winter'/><category term='algorithms'/><category term='stupidity'/><category term='home'/><category term='dell'/><category term='visualisation'/><category term='academia'/><category term='applications'/><category term='rsi'/><category term='mouse'/><category term='paulcusick'/><category term='opensource'/><category term='intrusion'/><category term='trains'/><category term='fantasy'/><category term='python'/><category term='amazon'/><category term='haskell'/><category term='functional'/><category term='comp1016'/><category term='family'/><category term='windows'/><category term='maintenance'/><category term='eclipse'/><category term='image'/><category term='mashup'/><category term='shadowmarch'/><category term='football'/><category term='work'/><category term='laptop'/><category term='teaching'/><category term='hardware'/><category term='science'/><category term='linux'/><category term='facebook'/><category term='tuitionfees'/><category term='tadwilliams'/><category term='research'/><category term='java'/><category term='authentication'/><category term='photography'/><category term='computerscience'/><category term='security'/><category term='programming'/><category term='holiday'/><category term='graphics'/><category term='injury'/><category term='music'/><category term='django'/><category term='publishing'/><category term='kindle'/><category term='leeds'/><category term='geolocation'/><category term='boohewerdine'/><category term='flickr'/><category term='twitter'/><category term='pain'/><category term='history'/><category term='microsoft'/><category term='quotes'/><category term='pygame'/><category term='mp3'/><category term='softwareengineering'/><category term='fun'/><category term='pomodoro'/><category term='maps'/><category term='ubuntu'/><category term='testing'/><category term='fiction'/><category term='snow'/><category term='karmic'/><category term='itunes'/><category term='crypto'/><category term='drugs'/><category term='computing'/><category term='university'/><category term='google'/><category term='tangerinedream'/><title type='text'>Pythoneering</title><subtitle type='html'>Random musings on IT, Python, software engineering, the web &amp;amp; other stuff</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>51</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-1505293353167689945</id><published>2011-06-14T11:17:00.001+01:00</published><updated>2011-06-14T11:18:40.715+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='algorithms'/><category scheme='http://www.blogger.com/atom/ns#' term='visualisation'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='computing'/><category scheme='http://www.blogger.com/atom/ns#' term='computerscience'/><title type='text'>The Impact of Computer Science</title><content type='html'>Hmm, been a while since I last blogged in any meaningful way - and I had such high hopes for this blog, too! I promise I'll be better over the summer.&lt;br /&gt;&lt;br /&gt;Anyway, I feel moved to post about something I came across just this morning: a &lt;a href="http://blog.blprnt.com/blog/blprnt/all-the-names"&gt;project to place the names of victims of 9/11 on a memorial in New York&lt;/a&gt;. The concept for the memorial was that names should be arranged not alphabetically, but rather according to where people were and who they were with when they died - linking victims through "meaningful adjacencies", in the words of the architect. It's a wonderful idea, but how could such a thing be achieved?&lt;br /&gt;&lt;br /&gt;This is, of course, precisely the kind of problem that computer scientists like to tackle. I won't go into the details here, other than to note that guy implementing this, Jer Thorp, made some interesting use of &lt;a href="http://processing.org/"&gt;Processing&lt;/a&gt; for the visualisation of victim relationships and name placement. You can read &lt;a href="http://blog.blprnt.com/blog/blprnt/all-the-names"&gt;Jer's blog entry&lt;/a&gt; if you want to know more.&lt;br /&gt;&lt;br /&gt;What strikes me most about this work is that it represents a very human and emotionally significant application of computer science. It is easy to fall into the trap of thinking that CS makes an impact only by improving technology, but this little project demonstrates brilliantly that it has the capacity to connect with human beings more directly than that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-1505293353167689945?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/1505293353167689945/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2011/06/impact-of-computer-science.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/1505293353167689945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/1505293353167689945'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2011/06/impact-of-computer-science.html' title='The Impact of Computer Science'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-1966603473264093287</id><published>2011-03-31T15:51:00.000+01:00</published><updated>2011-03-31T15:51:02.976+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='university'/><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><category scheme='http://www.blogger.com/atom/ns#' term='flickr'/><category scheme='http://www.blogger.com/atom/ns#' term='leeds'/><category scheme='http://www.blogger.com/atom/ns#' term='ucu'/><title type='text'>UCU Strikes</title><content type='html'>&lt;p&gt;My photos from last week's UCU strike action are available as a &lt;a href="http://www.flickr.com/photos/nickefford/sets/72157626327011736/"&gt;set&lt;/a&gt; and as a &lt;a href="http://www.flickr.com/photos/nickefford/sets/72157626327011736/show/"&gt;slideshow&lt;/a&gt;:&lt;/p&gt;&lt;object width="400" height="300"&gt; &lt;param name="flashvars" value="offsite=true&amp;lang=en-us&amp;page_show_url=%2Fphotos%2Fnickefford%2Fsets%2F72157626327011736%2Fshow%2F&amp;page_show_back_url=%2Fphotos%2Fnickefford%2Fsets%2F72157626327011736%2F&amp;set_id=72157626327011736&amp;jump_to="&gt;&lt;/param&gt;&lt;param name="movie" value="http://www.flickr.com/apps/slideshow/show.swf?v=71649"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/slideshow/show.swf?v=71649" allowFullScreen="true" flashvars="offsite=true&amp;lang=en-us&amp;page_show_url=%2Fphotos%2Fnickefford%2Fsets%2F72157626327011736%2Fshow%2F&amp;page_show_back_url=%2Fphotos%2Fnickefford%2Fsets%2F72157626327011736%2F&amp;set_id=72157626327011736&amp;jump_to=" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-1966603473264093287?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/1966603473264093287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2011/03/ucu-strikes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/1966603473264093287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/1966603473264093287'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2011/03/ucu-strikes.html' title='UCU Strikes'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-8261286489750309606</id><published>2011-03-03T00:02:00.001Z</published><updated>2011-03-31T16:19:03.351+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shadowmarch'/><category scheme='http://www.blogger.com/atom/ns#' term='tadwilliams'/><category scheme='http://www.blogger.com/atom/ns#' term='kindle'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='amazon'/><category scheme='http://www.blogger.com/atom/ns#' term='fiction'/><category scheme='http://www.blogger.com/atom/ns#' term='fantasy'/><category scheme='http://www.blogger.com/atom/ns#' term='publishing'/><title type='text'>Shadowmarch</title><content type='html'>&lt;p&gt;I'm a big fan of the writing of &lt;a href="http://www.tadwilliams.com/"&gt;Tad Williams&lt;/a&gt;, and the other day I finished reading &lt;a href="http://www.amazon.co.uk/gp/product/1841499234?ie=UTF8&amp;tag=sy32securecom-21&amp;linkCode=as2&amp;camp=1634&amp;creative=19450&amp;creativeASIN=1841499234"&gt;&lt;i&gt;Shadowheart&lt;/i&gt;&lt;/a&gt;&lt;img src="http://www.assoc-amazon.co.uk/e/ir?t=sy32securecom-21&amp;l=as2&amp;o=2&amp;a=1841499234" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; - the final volume of his &lt;i&gt;Shadowmarch&lt;/i&gt; tetralogy.&lt;/p&gt;&lt;p&gt;Those familiar with Tad's work will know of his earlier forays into epic fantasy, such as the &lt;i&gt;Memory, Sorrow &amp;amp; Thorn&lt;/i&gt; series with which he made his name a couple of decades ago. It is interesting to compare this recent saga with that earlier work.&lt;/p&gt;&lt;p&gt;The &lt;i&gt;Memory, Sorrow &amp;amp; Thorn&lt;/i&gt; books flirt with the cliches of fantasy fiction - magical swords, prophecy, etc - but this is leavened by touches of real originality. The elvish race featured in the books (the Sithi) are portrayed more as orientals than as stereotypical sylvan folk, for example. The stand-out feature for me was the large cast of interesting and well-rounded characters - perhaps none more interesting, well-rounded and complex than the guilt-ridden monk Cadrach.&lt;/p&gt;&lt;p&gt;So how does the &lt;i&gt;Shadowmarch&lt;/i&gt; series compare?&lt;/p&gt;&lt;p&gt;Whilst it revisits similar territory - a madman meddling with godlike forces that he cannot ultimately control - this an altogether more nuanced piece of work. It is still strongly character-driven, but has a more intricate and intriguing plot. The two main characters, twins Barrick &amp;amp; Briony Eddon, are far from classic hero/heroine material. Tad pulls off the difficult trick of making them deserving of sympathy but not entirely likeable: 'satisfyingly flawed' might be a good description - rather like Cadrach in the earlier books. That same subtlety is there in other aspects of the books, but there is also plenty of action to keep you greedily turning the pages - particularly in the extended final battle that is the core of &lt;i&gt;Shadowheart&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;In short: his best work to date, highly recommended for fans of epic fantasy.&lt;/p&gt;&lt;p&gt;As a postscript, let me note that I bought this from Amazon in hardback form, despite owning a Kindle for several months. It may be a bit OCD, but it would have bothered me to have three hardbacks plus a purely digital version to complete the set! I almost regret the decision now, because I found the bulk, weight and small print size of the physical book to be very off-putting after having got used to the Kindle...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-8261286489750309606?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/8261286489750309606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2011/03/shadowmarch.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/8261286489750309606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/8261286489750309606'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2011/03/shadowmarch.html' title='Shadowmarch'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-6868829977696000946</id><published>2011-01-31T20:29:00.000Z</published><updated>2011-01-31T20:29:16.700Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><category scheme='http://www.blogger.com/atom/ns#' term='flickr'/><category scheme='http://www.blogger.com/atom/ns#' term='facebook'/><title type='text'>Flickr</title><content type='html'>Perceptive quote from the NY Times:&lt;br /&gt;&lt;br /&gt;"No one questions Flickr’s appeal to photographers who post, admire and comment on a wealth of artistic images, many of which are magazine quality. Where Flickr is faltering is with people who want to store and share more mundane snapshots."&lt;br /&gt;&lt;br /&gt;I guess Facebook is where people are increasingly turning for casual photo sharing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-6868829977696000946?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/6868829977696000946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2011/01/flickr.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6868829977696000946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6868829977696000946'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2011/01/flickr.html' title='Flickr'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-2812581902706089659</id><published>2010-12-18T13:20:00.001Z</published><updated>2010-12-18T13:22:28.952Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='university'/><category scheme='http://www.blogger.com/atom/ns#' term='academia'/><category scheme='http://www.blogger.com/atom/ns#' term='research'/><category scheme='http://www.blogger.com/atom/ns#' term='publishing'/><title type='text'>Open Access</title><content type='html'>I came across an interesting blog article discussing whether academics should &lt;a href="http://blogs.ch.cam.ac.uk/pmr/2010/12/10/should-i-publish-open-access/"&gt;strive to publish in open access journals&lt;/a&gt;. &amp;nbsp;I particularly liked this passage:&lt;br /&gt;&lt;br /&gt;"However in the information-saturated world you can’t read everything and traditionally journals have been a way of bundling content into packets for particular readers. In the electronic and multidisciplinary world this is no longer necessary (although it’s still common). So journals have become branding labels. They are a simplistic way of saying “this paper is better than that paper”. It’s a bit like Gramophone records used to be. Or book publishers...&amp;nbsp;So we’ve moved to a situations where scientists follow brands rather than make rational decisions. The university system reinforces this... And the publishing houses can make a lot of money out of promoting brands. Bibliometrics shows that one publishing house not far from Kings Cross has done exceptionally in promoting its brand for all sorts of disciplines. Does this mean that their papers are better, or simply that their marketeers are better? Why do people buy one fragrance as opposed to another? Or any other fashion accessory? It’s not the raw value of the item – it’s the perception that has been built up."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-2812581902706089659?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/2812581902706089659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/12/open-access.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2812581902706089659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2812581902706089659'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/12/open-access.html' title='Open Access'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-8862526897788530192</id><published>2010-12-13T21:16:00.000Z</published><updated>2010-12-13T21:16:00.168Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='education'/><category scheme='http://www.blogger.com/atom/ns#' term='cuts'/><category scheme='http://www.blogger.com/atom/ns#' term='tuitionfees'/><title type='text'>Alfie</title><content type='html'>Peter Hallward &lt;a href="http://www.timeshighereducation.co.uk/story.asp?sectioncode=26&amp;storycode=414573&amp;c=2"&gt;wrote in the THE&lt;/a&gt; of last week's demos thus:&lt;br /&gt;&lt;br /&gt;"The story of one Middlesex undergraduate who used to sit in on my MA classes, Alfie Meadows, is already notorious. He received a full-on blow to the side of his skull. My partner and I found him wandering in Parliament Square a little after 6pm, pale and distraught, looking for a way to go home. He had a large lump on the right side of his head. He said he’d been hit by the police and didn’t feel well. We took one look at him and walked him towards the nearest barricaded exit as quickly as possible. It took a few minutes to reach and then convince the taciturn wall of police blocking Great George Street to let him through their shields, but they refused to let me, my partner or anyone else accompany him in search of medical help. We assumed that he would receive immediate and appropriate treatment on the other side of the police wall as a matter of course, but in fact he was left to wander off on his own, towards Victoria.&lt;br /&gt;&lt;br /&gt;As it turns out, Alfie’s subsequent survival depended on three chance events. If his mother (a lecturer at Roehampton, who was also “contained” in Parliament Square) hadn’t received his phone call and caught up with him shortly afterwards, the odds are that he’d have passed out on the street. If they hadn’t then stumbled upon an ambulance waiting nearby, his diagnosis could have been fatally delayed. And if the driver of this ambulance hadn’t overruled an initial refusal of the A&amp;E department of the Chelsea and Westminster hospital to look at Alfie, his transfer to the Charing Cross neurological unit for emergency brain surgery might well have come too late."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-8862526897788530192?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/8862526897788530192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/12/alfie.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/8862526897788530192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/8862526897788530192'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/12/alfie.html' title='Alfie'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-6132462543652881330</id><published>2010-12-11T20:01:00.000Z</published><updated>2010-12-11T20:01:07.631Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='education'/><category scheme='http://www.blogger.com/atom/ns#' term='cuts'/><category scheme='http://www.blogger.com/atom/ns#' term='tuitionfees'/><title type='text'>Spineless</title><content type='html'>From a &lt;a href="http://www.guardian.co.uk/uk/2010/dec/10/tuition-fees-out-libdem-manifesto"&gt;Guardian interview with Tim Farron MP&lt;/a&gt;, president of the Lib Dems:&lt;br /&gt;&lt;br /&gt;"I am absolutely furious with the vice-chancellors as a cadre and I'll be careful not to call them all spineless – but I will call them all spineless.&lt;br /&gt;&lt;br /&gt;"No other public sector body, in this whole shake-up with the cuts, was in a position where they could say: 'Right, we'll accept our cut in the direct support we get from the state as long as we get to charge our clients.' Imagine if we had headteachers or NHS managers saying that – it's absolutely outrageous"&lt;br /&gt;&lt;br /&gt;Says it all, really.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-6132462543652881330?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/6132462543652881330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/12/spineless.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6132462543652881330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6132462543652881330'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/12/spineless.html' title='Spineless'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-8356831311742961283</id><published>2010-10-02T12:46:00.000+01:00</published><updated>2010-10-02T12:46:54.257+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='tablet'/><category scheme='http://www.blogger.com/atom/ns#' term='hardware'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><title type='text'>New Skills</title><content type='html'>Liked this quote from an &lt;a href="http://www.infoworld.com/"&gt;InfoWorld&lt;/a&gt; article on the forthcoming &lt;a href="http://www.infoworld.com/t/mobile-platforms/blackberry-playbook-rim-charts-course-away-java-me-102"&gt;BlackBerry PlayBook&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;According to RIM's website, Tablet OS developers are currently slated to build apps in HTML5/CSS/JavaScript bundles or in Flash. "Add a new dimension to your BlackBerry development skills and create compelling applications for a new mobile form factor that complements your existing application" appears to be the euphemism that Marketing cooked up for "you're going to have to learn a whole new set of development tools".&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-8356831311742961283?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/8356831311742961283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/10/new-skills.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/8356831311742961283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/8356831311742961283'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/10/new-skills.html' title='New Skills'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-3761367698692392961</id><published>2010-09-20T11:19:00.000+01:00</published><updated>2010-09-20T11:19:27.162+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='comp1016'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='authentication'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>Extra security for Google users</title><content type='html'>It looks like Google are &lt;a href="http://techcrunch.com/2010/09/20/google-secure-password/?utm_source=feedburner&amp;amp;utm_medium=feed&amp;amp;utm_campaign=Feed%3A+Techcrunch+%28TechCrunch%29&amp;amp;utm_content=Google+Reader"&gt;rolling out a beefed-up security model&lt;/a&gt;, based around &lt;a href="http://en.wikipedia.org/wiki/Two-factor_authentication"&gt;&lt;b&gt;two-factor authentication&lt;/b&gt;&lt;/a&gt;. This is where a person needs to provide &lt;i&gt;two&lt;/i&gt; forms of proof that they own the username with which they are attempting to log in.&lt;br /&gt;&lt;br /&gt;In most two-factor schemes, the first proof is a password or PIN and the second is either a physical token of some kind (key or card) or a biometric identifier such as a facial image or fingerprint scan. The idea is that whilst an attacker might well capture your password or PIN somehow, it is going to very difficult for them to also provide physical or biometric proof.&lt;br /&gt;&lt;br /&gt;For an organisation that can issue its employees with smart cards, this scheme works very well, but such a move would be completely impractical (and hideously expensive) for Google. Their solution is to use your mobile phone, instead!&lt;br /&gt;&lt;br /&gt;It works like this: you log in as normal with a username and password, but then you are taken to a second screen in which you must enter a six-digit verification code. This code is delivered to your phone (which you have previously associated with your Google account).&lt;br /&gt;&lt;br /&gt;The system seems to be designed around the assumption that users will have an iPhone, BlackBerry or Android device running the Google Authenticator app. Whilst the verification code can also be sent via SMS, I wonder whether this will be quite as efficient. Fortunately, Google provide the option to authenticate like this once per computer rather one per login, which is easier (albeit at the cost of reduced security).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-3761367698692392961?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/3761367698692392961/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/09/extra-security-for-google-users.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/3761367698692392961'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/3761367698692392961'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/09/extra-security-for-google-users.html' title='Extra security for Google users'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-4655323341485028807</id><published>2010-09-18T19:41:00.000+01:00</published><updated>2010-09-18T19:41:16.344+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='social'/><category scheme='http://www.blogger.com/atom/ns#' term='comp1016'/><category scheme='http://www.blogger.com/atom/ns#' term='facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><category scheme='http://www.blogger.com/atom/ns#' term='youtube'/><title type='text'>Security &amp; Social Networks</title><content type='html'>Talk about security in the context of social networks and many people will think first of privacy - perhaps citing &lt;a href="http://www.facebook.com/"&gt;Facebook&lt;/a&gt;'s convoluted and controversial approach to this important issue as an example. But the risks run deeper than that. Security firm &lt;a href="http://www.avg.com/gb-en/press-releases-news.ndi-232491"&gt;AVG reports&lt;/a&gt; that it has identified 11,701 compromised Facebook pages and 7,163 compromised &lt;a href="http://youtube.com/"&gt;YouTube&lt;/a&gt; pages.&lt;br /&gt;&lt;br /&gt;AVG note that students between 18 and 25 years old are most at risk of having their Facebook status 'jacked'; this particular age group is the biggest user of Facebook whilst at the same time being significantly less concerned about Internet security and privacy than the average member of the population.&lt;br /&gt;&lt;br /&gt;Something to think about the next time you log on?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-4655323341485028807?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/4655323341485028807/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/09/security-social-networks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4655323341485028807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4655323341485028807'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/09/security-social-networks.html' title='Security &amp; Social Networks'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-5927685719050277878</id><published>2010-09-03T22:56:00.000+01:00</published><updated>2010-09-03T22:56:16.064+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mp3'/><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='itunes'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>The Joy of iTunes</title><content type='html'>I find it curious that a company lauded for its design skills when it comes to hardware can get it so wrong with software. My &lt;a href="http://store.apple.com/uk/browse/home/shop_ipod/family/ipod_classic?mco=MTM3NDkxNjY"&gt;iPod Classic&lt;/a&gt; is an immensely cool and sexy piece of kit - almost lickable (to copy Stephen Fry's memorable description of his iPad) - and yet iTunes feels like the complete opposite: clunky, unintuitive, unreliable and fundamentally untrustworthy.&lt;br /&gt;&lt;br /&gt;My negativity stems from the number of serious bugs that have plagued me ever since I started using this benighted piece of software - bugs which Apple seems to have no interest in fixing, preferring instead to add half-arsed new features such as &lt;a href="http://www.joyoftech.com/joyoftech/joyimages/1150.gif"&gt;Genius&lt;/a&gt; and &lt;a href="http://mashable.com/2010/09/01/itunes-ping/"&gt;Ping&lt;/a&gt;. Here are a few examples:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Album artwork that disappears from individual tracks or is reduced to a lower resolution, seemingly at random&lt;/li&gt;&lt;li&gt;Overwriting of my edits to album information (track titles, genre, etc) - again seemingly at random&lt;/li&gt;&lt;li&gt;Splitting of a single album into several identically-titled albums by the same artist for no apparent reason&lt;/li&gt;&lt;/ul&gt;I encountered another instance of the last of these earlier today and managed to fix it by making all the tracks 'part of a compilation' and then clearing this flag from all the tracks. Logical, huh?&lt;br /&gt;&lt;br /&gt;This stuff isn't hard to do. I've not encountered any of these problems with the copy of my music library that I access from Linux using &lt;a href="http://banshee.fm/"&gt;Banshee&lt;/a&gt;, for example. So how come a big, high-profile hardware/software developer can't get it right?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-5927685719050277878?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/5927685719050277878/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/09/joy-of-itunes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/5927685719050277878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/5927685719050277878'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/09/joy-of-itunes.html' title='The Joy of iTunes'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-4720642354405311118</id><published>2010-08-27T12:27:00.000+01:00</published><updated>2010-08-27T12:27:32.809+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bugs'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='softwareengineering'/><category scheme='http://www.blogger.com/atom/ns#' term='trains'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><category scheme='http://www.blogger.com/atom/ns#' term='transport'/><title type='text'>Train Fail</title><content type='html'>After&amp;nbsp; booking a train ticket for the HEA-ICS annual conference in Durham, this is the response I got:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_36V6kpTPt8E/THeK4fWCl8I/AAAAAAAAAyQ/mlS7Hg2_b4E/s1600/trainfail.png" imageanchor="1"&gt;&lt;img border="0" height="400" src="http://4.bp.blogspot.com/_36V6kpTPt8E/THeK4fWCl8I/AAAAAAAAAyQ/mlS7Hg2_b4E/s400/trainfail.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;Don't you just love inadequately-tested websites?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-4720642354405311118?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/4720642354405311118/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/08/train-fail.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4720642354405311118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4720642354405311118'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/08/train-fail.html' title='Train Fail'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_36V6kpTPt8E/THeK4fWCl8I/AAAAAAAAAyQ/mlS7Hg2_b4E/s72-c/trainfail.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-6801072409026529531</id><published>2010-08-23T12:51:00.000+01:00</published><updated>2010-08-23T12:51:15.648+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='family'/><category scheme='http://www.blogger.com/atom/ns#' term='holiday'/><category scheme='http://www.blogger.com/atom/ns#' term='home'/><title type='text'>Welcome Home</title><content type='html'>After a week of 40-degree temperatures on Kos, it was good to be greeted by cooler and more comfortable conditions. The two things that lodged in my travel-fatigued brain on arriving at Manchester Airport soon after dawn yesterday morning were me narrowly avoiding treading on the decapitated corpse of a mouse - presumably chewed up by the escalators - and the sight of a lass throwing her guts up just outside the terminal.&lt;br /&gt;&lt;br /&gt;Welcome to Britain!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-6801072409026529531?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/6801072409026529531/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/08/welcome-home.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6801072409026529531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6801072409026529531'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/08/welcome-home.html' title='Welcome Home'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-4263575632984563085</id><published>2010-08-03T17:17:00.000+01:00</published><updated>2010-08-03T17:17:14.815+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pomodoro'/><category scheme='http://www.blogger.com/atom/ns#' term='work'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='rsi'/><title type='text'>Pomodoro Technique</title><content type='html'>&lt;div class="zemanta-img separator" style="clear: right;"&gt;&lt;a href="http://commons.wikipedia.org/wiki/File:Il_pomodoro.jpg" style="clear: right; display: block; float: right; margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="Pomodoro Timer" height="200" src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Il_pomodoro.jpg/300px-Il_pomodoro.jpg" style="border: medium none; font-size: 0.8em;" width="200" /&gt;&lt;/a&gt;&lt;span class="zemanta-img-attribution" style="clear: both; float: right; margin-left: 1em; margin-right: 1em;"&gt;Image via &lt;a href="http://commons.wikipedia.org/wiki/File:Il_pomodoro.jpg"&gt;Wikipedia&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;I've just started experimenting with &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Pomodoro_Technique" rel="wikipedia" title="Pomodoro Technique"&gt;Pomodoro Technique&lt;/a&gt;, partly in the hope of improving productivity and achieving a more sustainable working pace, partly as a way of rigorously embedding breaks from the keyboard and mouse into my working habits so as to stave off the dreaded RSI. Staffan Nöteberg's book &lt;a href="http://pragprog.com/titles/snfocus/pomodoro-technique-illustrated"&gt;&lt;i&gt;Pomodoro Technique Illustrated&lt;/i&gt;&lt;/a&gt; is proving to be a useful and entertaining guide.  &lt;br /&gt;&lt;div class="zemanta-pixie" style="height: 15px; margin-top: 10px;"&gt;&lt;a class="zemanta-pixie-a" href="http://www.zemanta.com/" title="Enhanced by Zemanta"&gt;&lt;img alt="Enhanced by Zemanta" class="zemanta-pixie-img" src="http://img.zemanta.com/zemified_e.png?x-id=52d0e7a1-af9f-4127-a346-e59d7f93f44c" style="border: medium none; float: right;" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-4263575632984563085?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/4263575632984563085/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/08/pomodoro-technique.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4263575632984563085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4263575632984563085'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/08/pomodoro-technique.html' title='Pomodoro Technique'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-1333297857037577613</id><published>2010-07-27T23:25:00.002+01:00</published><updated>2010-07-28T11:36:57.139+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Teaching preparations</title><content type='html'>Summer is in full swing now and many of us at work are turning our attention to developing modules ready for teaching in September.&lt;br /&gt;&lt;br /&gt;I will once again be teaching introductory programming to our incoming students, using Python (of course :) - although the major change for this year is a move from Python 2.6 to &lt;a href="http://www.python.org/download/releases/3.1.2/"&gt;Python 3.1&lt;/a&gt;. In addition, I'm involved in three modules on our brand-new &lt;a href="http://www.engineering.leeds.ac.uk/ug/courses/BS-IT.shtml"&gt;IT degree&lt;/a&gt;: IT Infrastructure, Web Development and Project Management.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-1333297857037577613?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/1333297857037577613/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/07/teaching-preparations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/1333297857037577613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/1333297857037577613'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/07/teaching-preparations.html' title='Teaching preparations'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-4278674728934219169</id><published>2010-07-27T22:57:00.004+01:00</published><updated>2010-07-27T23:28:16.977+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tangerinedream'/><category scheme='http://www.blogger.com/atom/ns#' term='mp3'/><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='amazon'/><title type='text'>Digital Music Pricing Weirdness</title><content type='html'>&lt;div class="zemanta-img separator" style="clear: right;"&gt;&lt;a href="http://en.wikipedia.org/wiki/File:Encore.png" style="clear: right; display: block; float: right; margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="Encore (Tangerine Dream album)" height="200" src="http://upload.wikimedia.org/wikipedia/en/3/32/Encore.png" style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial; font-size: 0.8em;" width="200" /&gt;&lt;/a&gt;&lt;span class="zemanta-img-attribution" style="clear: both; float: right; margin-left: 1em; margin-right: 1em;"&gt;Image via &lt;a href="http://en.wikipedia.org/wiki/File:Encore.png"&gt;Wikipedia&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;Can anyone tell me how Amazon can sell Tangerine Dream's &lt;a href="http://www.amazon.co.uk/gp/product/B001J76WU0?ie=UTF8&amp;amp;tag=sy32securecom-21&amp;amp;linkCode=as2&amp;amp;camp=1634&amp;amp;creative=19450&amp;amp;creativeASIN=B001J76WU0"&gt;&lt;i&gt;Encore&lt;/i&gt;&lt;/a&gt;&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.co.uk/e/ir?t=sy32securecom-21&amp;amp;l=as2&amp;amp;o=2&amp;amp;a=B001J76WU0" style="border: none !important; margin: 0px !important;" width="1" /&gt; live album as an MP3 download for £4.99 yet sell its four individual tracks for £4.49 &lt;i&gt;each&lt;/i&gt;?&lt;br /&gt;&lt;div class="zemanta-pixie" style="height: 15px; margin-top: 10px;"&gt;&lt;a class="zemanta-pixie-a" href="http://www.zemanta.com/" title="Enhanced by Zemanta"&gt;&lt;img alt="Enhanced by Zemanta" class="zemanta-pixie-img" src="http://img.zemanta.com/zemified_e.png?x-id=715c38cf-2b8b-4e03-8f1b-320d6239bda4" style="border: none; float: right;" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-4278674728934219169?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/4278674728934219169/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/07/digital-music-pricing-weirdness.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4278674728934219169'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4278674728934219169'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/07/digital-music-pricing-weirdness.html' title='Digital Music Pricing Weirdness'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-9034696648182578254</id><published>2010-06-29T00:30:00.000+01:00</published><updated>2010-06-29T00:30:57.209+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maintenance'/><category scheme='http://www.blogger.com/atom/ns#' term='hardware'/><title type='text'>It Lives!</title><content type='html'>Shortly (and coincidentally) after the previously mentioned upgrade to Ubuntu Lucid, my PC went into a sulk - shutting down and refusing to boot up again. Pressing the Power On button caused the fans to spin up for about a second before everything went dead.&lt;br /&gt;&lt;br /&gt;Poking around the motherboard's power connector with a multimeter confirmed that the problem lay with the PSU. £45 got me a new unit from the local Maplin Electronics - 700W rather than the 580W of the original that came with the PC (best to be on the safe side :) Fitting was straightfoward and everything seems to be working swimmingly once more.&lt;br /&gt;&lt;br /&gt;There's a certain satisfaction to be had from fixing something yourself...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-9034696648182578254?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/9034696648182578254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/06/it-lives.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/9034696648182578254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/9034696648182578254'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/06/it-lives.html' title='It Lives!'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-172526924493536647</id><published>2010-06-26T13:30:00.000+01:00</published><updated>2010-06-26T13:30:56.087+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='lucid'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Upgrading</title><content type='html'>I've upgraded my &lt;a href="http://www.ubuntulinux.org/"&gt;Ubuntu&lt;/a&gt; machine at home to Lucid without any major issues.&lt;br /&gt;&lt;br /&gt;I like the new look and feel and would probably make the effort to get used to the new window button positioning, were it not for the fact that I have to use Fedora at work (plus Windows occasionally at work and at home).&lt;br /&gt;&lt;br /&gt;Gwibber is a promising addition, although it isn't quite as robust as I would like; it took several attempts and a detailed examination of bug reports in &lt;a href="https://bugs.launchpad.net/gwibber/+bug/552227"&gt;Launchpad &lt;/a&gt;before I could successful add my Facebook account to it.&lt;br /&gt;&lt;br /&gt;I've also discovered that screen lock no longer works properly after having upgraded from the open source fglrx graphics card driver to the proprietary version.&lt;br /&gt;&lt;br /&gt;On the plus side, sound works better than it did before; I seem to have much better control over volume than was the case in Karmic.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-172526924493536647?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/172526924493536647/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/06/upgrading.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/172526924493536647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/172526924493536647'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/06/upgrading.html' title='Upgrading'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-6747625653087215195</id><published>2010-06-21T21:52:00.001+01:00</published><updated>2010-06-22T10:50:51.201+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='university'/><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><category scheme='http://www.blogger.com/atom/ns#' term='flickr'/><category scheme='http://www.blogger.com/atom/ns#' term='ucu'/><title type='text'>United For Education</title><content type='html'>My photos from today's &lt;a href="http://unitedforeducation.org.uk/"&gt;United For Education&lt;/a&gt; day of action are now on Flickr, as a &lt;a href="http://www.flickr.com/photos/nickefford/sets/72157624201115133/"&gt;set&lt;/a&gt; and as a &lt;a href="http://www.flickr.com/photos/nickefford/sets/72157624201115133/show/"&gt;slideshow&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;object width="400" height="300"&gt; &lt;param name="flashvars" value="offsite=true&amp;lang=en-us&amp;page_show_url=%2Fphotos%2Fnickefford%2Fsets%2F72157624201115133%2Fshow%2F&amp;page_show_back_url=%2Fphotos%2Fnickefford%2Fsets%2F72157624201115133%2F&amp;set_id=72157624201115133&amp;jump_to="&gt;&lt;/param&gt;&lt;param name="movie" value="http://www.flickr.com/apps/slideshow/show.swf?v=71649"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/slideshow/show.swf?v=71649" allowFullScreen="true" flashvars="offsite=true&amp;lang=en-us&amp;page_show_url=%2Fphotos%2Fnickefford%2Fsets%2F72157624201115133%2Fshow%2F&amp;page_show_back_url=%2Fphotos%2Fnickefford%2Fsets%2F72157624201115133%2F&amp;set_id=72157624201115133&amp;jump_to=" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-6747625653087215195?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/6747625653087215195/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/06/united-for-education.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6747625653087215195'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6747625653087215195'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/06/united-for-education.html' title='United For Education'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-4378287284130106426</id><published>2010-06-21T11:14:00.002+01:00</published><updated>2010-06-22T10:49:45.634+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maps'/><category scheme='http://www.blogger.com/atom/ns#' term='visualisation'/><category scheme='http://www.blogger.com/atom/ns#' term='trains'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><category scheme='http://www.blogger.com/atom/ns#' term='transport'/><title type='text'>Live train and tube maps</title><content type='html'>One of the nicest mashups I've seen shows approximately live maps for &lt;a href="http://www.traintimes.org.uk/map/"&gt;UK mainline trains&lt;/a&gt; and the &lt;a href="http://www.traintimes.org.uk/map/tube/"&gt;London Underground&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I was particularly taken by a view of &lt;a href="http://www.traintimes.org.uk/map/?lds"&gt;trains to and from Leeds&lt;/a&gt; (especially after checking the box to move trains at 10x normal speed).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-4378287284130106426?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/4378287284130106426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/06/live-train-and-tube-maps.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4378287284130106426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4378287284130106426'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/06/live-train-and-tube-maps.html' title='Live train and tube maps'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-1964379932536700115</id><published>2010-06-19T19:57:00.002+01:00</published><updated>2010-06-21T10:47:48.408+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='django'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><title type='text'>Django 1.2 E-commerce</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_36V6kpTPt8E/TB0Q-4USmlI/AAAAAAAAAxw/4gNMKgGhS_M/s1600/DjangoEcommerce.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/_36V6kpTPt8E/TB0Q-4USmlI/AAAAAAAAAxw/4gNMKgGhS_M/s200/DjangoEcommerce.jpg" width="161" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://www.packtpub.com/"&gt;Packt Publishing&lt;/a&gt; have sent me a copy of &lt;a href="http://www.packtpub.com/django-1-2-e-commerce-build-powerful-applications/book?utm_source=pythoneering.blogspot.com&amp;amp;utm_medium=bookrev&amp;amp;utm_content=blog&amp;amp;utm_campaign=mdb_003678"&gt;&lt;i&gt;Django 1.2 E-commerce&lt;/i&gt;&lt;/a&gt; to review. Looks interesting. I've got a number of Packt books and some of them (&lt;i&gt;&lt;a href="https://www.packtpub.com/learning-jquery-1.3/book"&gt;Learning JQuery&lt;/a&gt;&lt;/i&gt;, for example) have been really good. Hopefully this will be up to the same standard.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://www.packtpub.com/sites/default/files/7009-chapter-2-setting-up-shop-in-30-minutes_0.pdf"&gt;Chapter 2&lt;/a&gt; is available as a free download, if you want to check it out for yourselves...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-1964379932536700115?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/1964379932536700115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/06/django-12-e-commerce.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/1964379932536700115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/1964379932536700115'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/06/django-12-e-commerce.html' title='Django 1.2 E-commerce'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_36V6kpTPt8E/TB0Q-4USmlI/AAAAAAAAAxw/4gNMKgGhS_M/s72-c/DjangoEcommerce.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-7385128161086240229</id><published>2010-06-19T11:48:00.000+01:00</published><updated>2010-06-19T11:48:56.153+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bugs'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='softwareengineering'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><title type='text'>Dear None...</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_36V6kpTPt8E/TBySIragjvI/AAAAAAAAAxo/5RJn1ZRH7Ko/s1600/None.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="220" src="http://1.bp.blogspot.com/_36V6kpTPt8E/TBySIragjvI/AAAAAAAAAxo/5RJn1ZRH7Ko/s400/None.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Got this via email after having registered for one of those discount cards.&lt;br /&gt;&lt;br /&gt;It is interesting to speculate on the cause. If I had to put money on it, I'd bet that &lt;a href="http://today.yougov.co.uk/"&gt;YouGov&lt;/a&gt; send these emails via a 'mail merge' application of some kind that merges on a name field in the customer database given to them by Costa. Perhaps this name field is blank in some cases, and the mail merge app fails to check this. (If I had to hazard a guess, I'd say that the 'None' suggests an app written in Python :)&lt;br /&gt;&lt;br /&gt;Regardless of the precise reasons for this error, we can say with certainty that it points to inadequate testing of the application. The developers have made assumptions about data completeness/validity that are not justified in reality. Testing with realistic data would have exposed those assumptions, prompting a simple modification to the code that substitutes a suitable default ('Valued Customer', for example) if no name is available.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-7385128161086240229?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/7385128161086240229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/06/dear-none.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/7385128161086240229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/7385128161086240229'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/06/dear-none.html' title='Dear None...'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_36V6kpTPt8E/TBySIragjvI/AAAAAAAAAxo/5RJn1ZRH7Ko/s72-c/None.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-6045063612458995014</id><published>2010-04-21T15:39:00.004+01:00</published><updated>2010-04-21T15:49:38.423+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='flickr'/><category scheme='http://www.blogger.com/atom/ns#' term='crypto'/><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='history'/><category scheme='http://www.blogger.com/atom/ns#' term='computing'/><title type='text'>Pilgrimage</title><content type='html'>&lt;a href="http://www.flickr.com/photos/nickefford/4530798117/" title="Colossus by Nick Efford, on Flickr"&gt;&lt;img src="http://farm5.static.flickr.com/4068/4530798117_aa5249b6a8_m.jpg" width="157" height="240" alt="Colossus" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Last week I at long last paid a visit to &lt;a href="http://www.bletchleypark.org.uk/"&gt;Bletchley Park&lt;/a&gt;, the centre of codebreaking efforts for the British during World War II and the birthplace of modern computing.  The picture here shows the reconstructed Colossus Mk II, the world's first semi-programmable digital electronic computer, which helped to crack the Lorentz cipher used by the German High Command.&lt;br /&gt;&lt;br /&gt;For a geek like me, standing in front of this as it whirred and clicked was a near-religious experience!  The Bletchley Park huts are well worth a visit for anyone interested in cryptography or military history, and the existence of Colossus and &lt;a href="http://www.tnmoc.org/"&gt;The National Museum of Computing&lt;/a&gt; on site is the icing on the cake.&lt;br /&gt;&lt;br /&gt;My photos of the day are available for viewing as a &lt;a href="http://www.flickr.com/photos/nickefford/sets/72157623755917565/"&gt;Flickr set&lt;/a&gt; or &lt;a href="http://www.flickr.com/photos/nickefford/sets/72157623755917565/show/"&gt;slideshow&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-6045063612458995014?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/6045063612458995014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/04/pilgrimage.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6045063612458995014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6045063612458995014'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/04/pilgrimage.html' title='Pilgrimage'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm5.static.flickr.com/4068/4530798117_aa5249b6a8_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-6071671374353324522</id><published>2010-03-11T12:00:00.002Z</published><updated>2010-03-11T12:00:10.372Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='university'/><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><category scheme='http://www.blogger.com/atom/ns#' term='flickr'/><category scheme='http://www.blogger.com/atom/ns#' term='ucu'/><title type='text'>Leeds UCU Rally</title><content type='html'>Pictures from last week's &lt;a href="http://leedsucu.wordpress.com/"&gt;Leeds UCU&lt;/a&gt; Rally:&lt;br /&gt;&lt;object width="400" height="300"&gt; &lt;param name="flashvars" value="offsite=true&amp;lang=en-us&amp;page_show_url=%2Fphotos%2Fnickefford%2Fsets%2F72157623559057300%2Fshow%2F&amp;page_show_back_url=%2Fphotos%2Fnickefford%2Fsets%2F72157623559057300%2F&amp;set_id=72157623559057300&amp;jump_to="&gt;&lt;/param&gt;&lt;param name="movie" value="http://www.flickr.com/apps/slideshow/show.swf?v=71649"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/slideshow/show.swf?v=71649" allowFullScreen="true" flashvars="offsite=true&amp;lang=en-us&amp;page_show_url=%2Fphotos%2Fnickefford%2Fsets%2F72157623559057300%2Fshow%2F&amp;page_show_back_url=%2Fphotos%2Fnickefford%2Fsets%2F72157623559057300%2F&amp;set_id=72157623559057300&amp;jump_to=" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-6071671374353324522?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/6071671374353324522/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/03/leeds-ucu-rally.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6071671374353324522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6071671374353324522'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/03/leeds-ucu-rally.html' title='Leeds UCU Rally'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-5314713387013446466</id><published>2010-03-10T22:39:00.000Z</published><updated>2010-03-10T22:39:05.246Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><title type='text'>Twittering</title><content type='html'>I've succumbed and created a &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; account for myself - not really out of a burning desire to start using it, but rather because last week I gave a lecture to my students on how Python could be used for Internet programming at the application level. I already had examples of how to access Flickr and Google services, but Twitter seemed like another good example to use because students are familiar with it as a 'Web 2.0' service and because there is a nice, easy-to-use library available for its API: &lt;a href="http://code.google.com/p/python-twitter/"&gt;python-twitter&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I showed the students a simple program to post a status update. I ran it using my newly-created Twitter account (&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;python33r&lt;/span&gt;) and then showed them the tweet appearing on &lt;a href="http://twitter.com/python33r/"&gt;my Twitter page&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I didn't think I'd want to continue using the service, but I happened to start following a few people/organisations of interest to me and it has provided a couple of useful notifications already.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-5314713387013446466?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/5314713387013446466/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/03/twittering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/5314713387013446466'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/5314713387013446466'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/03/twittering.html' title='Twittering'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-5215293825388341044</id><published>2010-03-10T19:57:00.001Z</published><updated>2010-03-10T19:58:26.943Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='news'/><category scheme='http://www.blogger.com/atom/ns#' term='football'/><category scheme='http://www.blogger.com/atom/ns#' term='quotes'/><category scheme='http://www.blogger.com/atom/ns#' term='science'/><title type='text'>Relegation</title><content type='html'>It seems that &lt;a href="http://www.timeshighereducation.co.uk/story.asp?sectioncode=26&amp;storycode=410690&amp;c=1"&gt;the UK risks relegation from the 'Premier League' of scientific nations&lt;/a&gt;.  Sir Martin Taylor, former vice-president of the Royal Society has said that "we are a bit like Manchester United, but if we are not careful we could end up a bit like Leeds United".&lt;br /&gt;&lt;br /&gt;Ouch.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-5215293825388341044?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/5215293825388341044/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/03/relegation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/5215293825388341044'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/5215293825388341044'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/03/relegation.html' title='Relegation'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-909346152151276511</id><published>2010-02-18T10:29:00.000Z</published><updated>2010-02-18T10:29:10.091Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='work'/><category scheme='http://www.blogger.com/atom/ns#' term='drugs'/><category scheme='http://www.blogger.com/atom/ns#' term='injury'/><category scheme='http://www.blogger.com/atom/ns#' term='pain'/><title type='text'>Back Trouble</title><content type='html'>Today, I was supposed to be supervising a couple of lab classes on object-oriented programming with Python, but instead I find myself lying in bed, blogging (thank &amp;lt;insert deity of choice&amp;gt; for netbooks :)&lt;br /&gt;&lt;br /&gt;Yesterday morning, I suffered a prolapsed disc that popped back in but left my back in spasm. Of course, I didn't realise this at the time, and foolishly shuffled into work, thinking that if I could move around (albeit gingerly) I would be OK. I eventually made it in to the office and sat down to deal with emails and other chores. After about 30 minutes, I attempted to get up out of my chair and found that I couldn't straighten up, nor could I walk properly! I rang my wife, who came in to pick me up and take me to the doctor.&lt;br /&gt;&lt;br /&gt;My problem was diagnosed more or less instantly, thanks to my "duck's arse walk", as the doc so eloquently put it. &amp;nbsp;I was prescribed bed rest and a bunch of drugs, and advised to seek physiotherapy once I am a bit more mobile.&lt;br /&gt;&lt;br /&gt;So here I am, feeling somewhat relaxed courtesy of Diazepam and Codeine, wondering what to do with myself for the next few days...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-909346152151276511?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/909346152151276511/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/02/back-trouble.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/909346152151276511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/909346152151276511'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/02/back-trouble.html' title='Back Trouble'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-5390009759567986781</id><published>2010-01-27T23:42:00.000Z</published><updated>2010-01-27T23:42:45.898Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='gnuplot'/><category scheme='http://www.blogger.com/atom/ns#' term='visualisation'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>Gnuplot in Action</title><content type='html'>I've used &lt;a href="http://www.gnuplot.info/"&gt;gnuplot&lt;/a&gt; for a long, long time without ever truly getting to grips with its intricacies - but I'm rectifying that with the aid of Philipp Janert's &lt;a href="http://www.manning.com/janert/"&gt;Gnuplot in Action&lt;/a&gt;. So far, I've learned three interesting and useful new things in the first thirty pages: a good sign!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-5390009759567986781?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/5390009759567986781/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/01/gnuplot-in-action.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/5390009759567986781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/5390009759567986781'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/01/gnuplot-in-action.html' title='Gnuplot in Action'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-2010133470701292387</id><published>2010-01-27T23:28:00.002Z</published><updated>2010-01-27T23:30:40.376Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='applications'/><category scheme='http://www.blogger.com/atom/ns#' term='microsoft'/><category scheme='http://www.blogger.com/atom/ns#' term='stupidity'/><title type='text'>Uninstall woes</title><content type='html'>Having bowed to pressure from the family and installed Microsoft Office 2007 on one of the family PCs, I figured that there is no further need for the copy of Microsoft Works that came pre-installed on the machine. But when I tried to remove Works, I was prompted to insert the installation CD!&lt;br /&gt;&lt;br /&gt;WTF? Why on earth should this be required? Most malware is easier to get off your system than this piece of crap.&lt;br /&gt;&lt;br /&gt;Anyway, I can't comply with the request because the CD was not supplied with the system when we bought it. Grrr...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-2010133470701292387?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/2010133470701292387/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/01/uninstall-woes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2010133470701292387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2010133470701292387'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/01/uninstall-woes.html' title='Uninstall woes'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-1971512694176268350</id><published>2010-01-08T14:16:00.002Z</published><updated>2010-01-08T14:22:32.625Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><category scheme='http://www.blogger.com/atom/ns#' term='flickr'/><category scheme='http://www.blogger.com/atom/ns#' term='fun'/><title type='text'>Flickr fun</title><content type='html'>I'm a &lt;a href="http://www.flickr.com/"&gt;Flickr&lt;/a&gt; devotee, and was interested to discover their &lt;a href="http://www.flickr.com/services/"&gt;App Garden&lt;/a&gt; - a place where home-grown applications that use the &lt;a href="http://www.flickr.com/services/api/"&gt;Flickr API&lt;/a&gt; can be promoted.&lt;br /&gt;&lt;br /&gt;One that particularly caught my eye is &lt;a href="http://velt.info/zex/clf/"&gt;Command-Line Flickr&lt;/a&gt; - a retro, textual interface that allows you to browse photostreams and even render individual pictures as ASCII art! Strange but rather cool.&lt;br /&gt;&lt;br /&gt;Here's the photo from &lt;a href="http://pythoneering.blogspot.com/2010/01/let-it-snow.html"&gt;yesterday's post&lt;/a&gt;, rendered in ASCII:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_36V6kpTPt8E/S0c_Qmlk7uI/AAAAAAAAAxc/j7YrzYZiKOs/s1600-h/clf.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_36V6kpTPt8E/S0c_Qmlk7uI/AAAAAAAAAxc/j7YrzYZiKOs/s320/clf.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-1971512694176268350?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/1971512694176268350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/01/flickr-fun.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/1971512694176268350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/1971512694176268350'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/01/flickr-fun.html' title='Flickr fun'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_36V6kpTPt8E/S0c_Qmlk7uI/AAAAAAAAAxc/j7YrzYZiKOs/s72-c/clf.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-4132369985362489076</id><published>2010-01-08T11:32:00.000Z</published><updated>2010-01-08T11:32:21.323Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='image'/><category scheme='http://www.blogger.com/atom/ns#' term='winter'/><category scheme='http://www.blogger.com/atom/ns#' term='snow'/><title type='text'>Frozen Britain</title><content type='html'>The BBC website has an &lt;a href="http://news.bbc.co.uk/1/hi/in_depth/8447023.stm"&gt;interesting NASA satellite image&lt;/a&gt; from yesterday, 7 January, showing the extent of the snow cover across the country.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-4132369985362489076?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/4132369985362489076/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/01/frozen-britain.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4132369985362489076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4132369985362489076'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/01/frozen-britain.html' title='Frozen Britain'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-3573663085382951363</id><published>2010-01-07T23:10:00.000Z</published><updated>2010-01-07T23:10:05.229Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><category scheme='http://www.blogger.com/atom/ns#' term='winter'/><category scheme='http://www.blogger.com/atom/ns#' term='snow'/><title type='text'>Let It Snow...</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_36V6kpTPt8E/S0ZpRxPslbI/AAAAAAAAAxU/u0UxV44bcgM/s1600-h/birdbox.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_36V6kpTPt8E/S0ZpRxPslbI/AAAAAAAAAxU/u0UxV44bcgM/s320/birdbox.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;We are deeply in the grip of winter at the moment, with plenty of snow on the ground, schools closed, etc. I was at home with the kids today and took my camera outside for the first time in a few weeks, to grab a few shots of interestingly-shaped accumulations of snow. Here, it looks like the nesting box in our back garden has acquired a quiff!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-3573663085382951363?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/3573663085382951363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/01/let-it-snow.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/3573663085382951363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/3573663085382951363'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/01/let-it-snow.html' title='Let It Snow...'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_36V6kpTPt8E/S0ZpRxPslbI/AAAAAAAAAxU/u0UxV44bcgM/s72-c/birdbox.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-6811893396625751208</id><published>2010-01-02T11:18:00.001Z</published><updated>2010-01-02T11:18:34.339Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Happy Birthday, Python!</title><content type='html'>It appears that Python &lt;a href="http://twitter.com/gvanrossum/status/7245136611"&gt;turned twenty&lt;/a&gt; a couple of days ago.&lt;br /&gt;&lt;br /&gt;I hope that the next twenty years will be as successful as the first twenty...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-6811893396625751208?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/6811893396625751208/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2010/01/happy-birthday-python.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6811893396625751208'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6811893396625751208'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2010/01/happy-birthday-python.html' title='Happy Birthday, Python!'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-2638046441528637927</id><published>2009-12-25T09:55:00.001Z</published><updated>2009-12-25T09:56:05.281Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='winter'/><category scheme='http://www.blogger.com/atom/ns#' term='snow'/><category scheme='http://www.blogger.com/atom/ns#' term='christmas'/><title type='text'>Merry Christmas!</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_36V6kpTPt8E/SzSL9S8wr0I/AAAAAAAAAxE/VBbwl9Pm6IU/s1600-h/snowman.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_36V6kpTPt8E/SzSL9S8wr0I/AAAAAAAAAxE/VBbwl9Pm6IU/s320/snowman.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-2638046441528637927?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/2638046441528637927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/merry-christmas.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2638046441528637927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2638046441528637927'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/merry-christmas.html' title='Merry Christmas!'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_36V6kpTPt8E/SzSL9S8wr0I/AAAAAAAAAxE/VBbwl9Pm6IU/s72-c/snowman.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-2301035096513868014</id><published>2009-12-22T21:09:00.000Z</published><updated>2009-12-22T21:09:53.890Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='functional'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>The Joy of Haskell</title><content type='html'>About a year ago, I spent the best part of a day playing with &lt;a href="http://www.haskell.org/"&gt;Haskell&lt;/a&gt;, which was long enough to intrigue me as to its possibilities but not long enough to develop any real understanding of the language. Since then, my functional programming urges have lain dormant - until last week, when I decided to dust off my copy of &lt;i&gt;&lt;a href="http://www.realworldhaskell.org/"&gt;Real World Haskell&lt;/a&gt;&lt;/i&gt; and spend a bit longer with the language.&lt;br /&gt;&lt;br /&gt;So far, it has been an enjoyable experience, albeit a demanding one at times. I'm very impressed by the elegance and expressive power of Haskell. I've just been reading about currying and function composition and can sense a broadening of my mental horizons somewhat akin to that which I felt on first encountering the UNIX tools philosophy. It was a revelation then to realise just how much more flexible UNIX could be than rival operating systems, thanks to the idea of having many small, simple utilities, controlled via command line flags and connected via pipes. I'm beginning to feel that Haskell offers analogous benefits, compared with the other languages that I've been using for so many years.&lt;br /&gt;&lt;br /&gt;That said, I'm encountering the odd thing that makes me cringe. A few of the functions seem to have rather ugly names - &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;putStrLn&lt;/span&gt; being a prime example. But I guess I can learn to live with that.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Real World Haskell&lt;/i&gt; seems to be pretty good. My only significant quibble so far concerns the exercises, which could do a better job of reinforcing and building on the concepts introduced in the text.&lt;br /&gt;&lt;br /&gt;It's too early to say whether my programming habits will be irrevocably changed by all this; I suppose it depends to a large extent on how much more time I'm prepared to spend on Haskell. I sense I'm on the verge of 'getting it', so who knows?...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-2301035096513868014?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/2301035096513868014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/joy-of-haskell.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2301035096513868014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2301035096513868014'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/joy-of-haskell.html' title='The Joy of Haskell'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-132588490605582357</id><published>2009-12-20T00:59:00.000Z</published><updated>2009-12-20T19:09:27.738Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Appropriate complexity in Java and Python</title><content type='html'>I've blogged &lt;a href="http://pythoneering.blogspot.com/2009/12/what-makes-programming-language-easy-to.html"&gt;previously&lt;/a&gt; that the notion of &lt;b&gt;appropriate complexity&lt;/b&gt; is important in determining how easy it will be to learn a programming language. Ideally, small, simple problems should be solvable with small, simple programs, and program size or complexity should not need to increase substantially if there is a small increase in the size or complexity of the problem - always assuming, of course, that we remain within the 'comfort zone' of the language.&lt;br /&gt;&lt;br /&gt;Let's consider how well Java meets this requirement by looking at the traditional first program: one that prints &lt;a href="http://en.wikipedia.org/wiki/Hello_world_program"&gt;"Hello, World!"&lt;/a&gt; on the console. If we were dogmatic about exploiting Java's object-oriented nature, then such a program would have to look something like this:&lt;br /&gt;&lt;pre class="brush: java"&gt;public class Greeting&lt;br /&gt;{&lt;br /&gt;  public void display()&lt;br /&gt;  {&lt;br /&gt;    System.out.println("Hello, World!");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public static void main(String[] args)&lt;br /&gt;  {&lt;br /&gt;    greeting = new Greeting();&lt;br /&gt;    greeting.display();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;A complete novice who is already nervous about the challenge of learning programming will probably regard this code with dismay and wonder just how much more difficult writing a non-trivial program is likely to be.&lt;br /&gt;&lt;br /&gt;One way of minimising the complexity is to develop and execute code within an environment that hides much of the 'scaffolding' - &lt;a href="http://www.bluej.org/"&gt;BlueJ&lt;/a&gt;, for example. Alternatively, we could simplify things by adopting a largely procedural style:&lt;br /&gt;&lt;pre class="brush: java"&gt;public class Greeting&lt;br /&gt;{&lt;br /&gt;  public static void main(String[] args)&lt;br /&gt;  {&lt;br /&gt;    System.out.println("Hello, World!");&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;But even this simpler code is replete with potentially confusing details. The novice will no doubt be able to identify the single line of code that causes a message to be printed on the console, but will wonder&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Why the line appears inside something called &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;main&lt;/span&gt;&lt;/li&gt;&lt;li&gt;What purpose is served by &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;String[] args&lt;/span&gt;&lt;/li&gt;&lt;li&gt;What the words &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;public&lt;/span&gt;, &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;static&lt;/span&gt; and &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;void&lt;/span&gt; signify&lt;/li&gt;&lt;li&gt;What a class is, and why the code has to be enclosed within it&lt;/li&gt;&lt;/ul&gt;How does one deal with such questions? Is it better to explain every detail of the program, running the risk of confusing or intimidating the less experienced, less confident students? Or is it better to defer explanations until later, running the risk that students will not be confident about writing their first few programs because they don't understand everything that they are expected to type? Both approaches clearly have drawbacks.&lt;br /&gt;&lt;br /&gt;Python suffers from no such problems, offering us what is surely the simplest version possible of the traditional first program:&lt;br /&gt;&lt;pre class="brush: python"&gt;print 'Hello, World!'&lt;br /&gt;&lt;/pre&gt;(The Python 3 version includes parentheses, of course, because &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;print&lt;/span&gt; is a built-in function rather than a statement in Python 3.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-132588490605582357?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/132588490605582357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/appropriate-complexity-in-java-and.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/132588490605582357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/132588490605582357'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/appropriate-complexity-in-java-and.html' title='Appropriate complexity in Java and Python'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-6690568466167800545</id><published>2009-12-19T15:06:00.000Z</published><updated>2009-12-19T15:06:49.305Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='paulcusick'/><title type='text'>Paul Cusick</title><content type='html'>Got an early present in the post the other day: &lt;a href="http://www.paulcusick.co.uk/"&gt;Paul Cusick&lt;/a&gt;'s &lt;i&gt;Focal Point&lt;/i&gt; CD. A nice touch was the handwritten postcard from Paul himself, wishing me a Happy Christmas!&lt;br /&gt;&lt;br /&gt;I discovered Paul via &lt;a href="http://last.fm/"&gt;last.fm&lt;/a&gt; and recommend that you check out his work if you are a fan of contemporary rock music - particularly if you like the 'modern prog rock' sound of bands such as &lt;a href="http://www.porcupinetree.com/"&gt;Porcupine Tree&lt;/a&gt; or &lt;a href="http://www.pineapplethief.com/"&gt;The Pineapple Thief&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="400" height="100" &gt;&lt;param name="movie" value="http://bandcamp.com/EmbeddedPlayer.swf/album=2264686780/size=venti/bgcol=FFFFFF/linkcol=4285BB/" /&gt;&lt;param name="quality" value="high" /&gt;&lt;param name="allowScriptAccess" value="never" /&gt;&lt;param name="allowNetworking" value="always" /&gt;&lt;param name="bgcolor" value="#FFFFFF" /&gt;&lt;embed src="http://bandcamp.com/EmbeddedPlayer.swf/album=2264686780/size=venti/bgcol=FFFFFF/linkcol=4285BB/" width="400" height="100" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" quality=high allowScriptAccess=never allowNetworking=always bgcolor=#FFFFFF &gt;&lt;/embed&gt;&lt;noembed&gt;&lt;a href="http://music.paulcusick.co.uk/album/focal-point-album"&gt;Focal Point by Paul Cusick&lt;/a&gt;&lt;/noembed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-6690568466167800545?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/6690568466167800545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/paul-cusick.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6690568466167800545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6690568466167800545'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/paul-cusick.html' title='Paul Cusick'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-4674033654371570975</id><published>2009-12-19T13:16:00.001Z</published><updated>2009-12-19T14:26:03.343Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Minimal surprise in Java and Python</title><content type='html'>I've blogged &lt;a href="http://pythoneering.blogspot.com/2009/12/what-makes-programming-language-easy-to.html"&gt;previously&lt;/a&gt; about the idea that a programming language will be easier to learn if it causes &lt;b&gt;minimal surprise&lt;/b&gt; to the learner. Let's consider a couple of examples here.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Integer Division&lt;/h3&gt;&lt;br /&gt;In common with other popular languages like C, C++, Java, C# and Ruby, Python 2 implements 'floor division' for integers - so evaluating &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;1/2&lt;/span&gt; will yield &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;0&lt;/span&gt;, for example. This is an unwelcome surprise for most programming novices, who naturally expect a language to implement the normal rules of arithmetic. In our experience of teaching Python 2 (and before that, Java and C++), most students make mistakes with integer division more than once before they learn to cope with this counterintuitive behaviour.&lt;br /&gt;&lt;br /&gt;Python 3 changes &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;int&lt;/span&gt; division so that it now returns a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;float&lt;/span&gt; value. The &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;//&lt;/span&gt; operator can be used to obtain the old behaviour:&lt;br /&gt;&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; 1 / 2&lt;br /&gt;0.5&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; 1 // 2&lt;br /&gt;0&lt;br /&gt;&lt;/pre&gt;For some programmers whose expectations have been shaped by exposure to the C family of languages, this change has been the source of much anguish ever since it was first proposed in &lt;a href="http://www.python.org/dev/peps/pep-0238/"&gt;PEP 238&lt;/a&gt; back in 2001 (as can be seen in &lt;a href="http://groups.google.com/group/comp.lang.python/browse_thread/thread/fb904331950b1ea0/979ba69ca0884695?q=integer+division&amp;amp;lnk=ol&amp;amp;pli=1"&gt;comp.lang.python newsgroup discussion on the topic&lt;/a&gt;), but it removes what was clearly a significant hurdle for those new to programming.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Console I/O&lt;/h3&gt;&lt;br /&gt;In &lt;a href="http://pythoneering.blogspot.com/2009/12/minimal-redundancy-in-java-and-python-2.html"&gt;another post&lt;/a&gt;, I described the asymmetry in console I/O that exists in Python 2 as an example of redundancy, but it can also be viewed as an unexpected surprise. And there's something else, about console input specifically, that can be surprising to Python newbies.&lt;br /&gt;&lt;br /&gt;For a long time, Python has had &lt;i&gt;two&lt;/i&gt; built-in functions that read from the console: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;input&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;raw_input&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The first of these reads a string of characters &lt;i&gt;and attempts to evaluate them&lt;/i&gt;, such that a sequence of digits yields an integer value, characters enclosed in quotes yield a string, etc. Unfortunately, this is less useful than it sounds. Consider the following simple Python 2 program:&lt;br /&gt;&lt;pre class="brush: python"&gt;# hello.py - a program that greets you&lt;br /&gt;&lt;br /&gt;name = input('Who are you? ')&lt;br /&gt;print 'Hello', name&lt;br /&gt;&lt;/pre&gt;Here are two attempts to run this program:&lt;br /&gt;&lt;pre&gt;$ python hello.py&lt;br /&gt;Enter your name: nick&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "hello.py", line 3, in &amp;lt;module&amp;gt;&lt;br /&gt;    name = input('Who are you? ')&lt;br /&gt;  File "&amp;lt;string&amp;gt;", line 1, in &amp;lt;module&amp;gt;&lt;br /&gt;NameError: name 'nick' is not defined&lt;br /&gt;&lt;br /&gt;$ python hello.py&lt;br /&gt;Enter your name: max&lt;br /&gt;Hello &amp;lt;built-in function max&amp;gt;&lt;br /&gt;&lt;/pre&gt;In both cases, the student running the program has forgotten that string input should be enclosed in quotes, with the result that Python treats the inputs as names of objects in the global namespace. The first attempt fails because there is no object named &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;nick&lt;/span&gt;, but the second attempt succeeds because Python has a built-in function named &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;max&lt;/span&gt;. Both results are surprising, even baffling, to programming novices.&lt;br /&gt;&lt;br /&gt;The less surprising option in Python 2 is to use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;raw_input&lt;/span&gt; instead of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;input&lt;/span&gt;.  The &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;raw_input&lt;/span&gt; function returns console input as a string object and allows the programmer to decide exactly how this string should be handled. The string can be left alone in cases where text is expected (as in &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;hello.py&lt;/span&gt;) or it can be converted explicitly to the required type:&lt;br /&gt;&lt;pre class="brush: python"&gt;number = float(raw_input('Enter a value: '))&lt;br /&gt;&lt;/pre&gt;We have seen many cases where students have used &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;input&lt;/span&gt; in their Python 2 programs, having failed to recognise that &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;raw_input&lt;/span&gt; is a safer, less confusing alternative (in spite of our attempts to explain this most carefully). Python 3 prevents such confusion by providing a single function named &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;input&lt;/span&gt;, equivalent to the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;raw_input&lt;/span&gt; function of earlier versions. Evaluation of the input string is still possible, but it must be done explicitly, with code like &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;eval(input())&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-4674033654371570975?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/4674033654371570975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/minimal-surprise-in-java-and-python.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4674033654371570975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4674033654371570975'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/minimal-surprise-in-java-and-python.html' title='Minimal surprise in Java and Python'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-1348707834637304507</id><published>2009-12-18T08:38:00.001Z</published><updated>2009-12-18T10:26:25.393Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Separation of concerns in Java and Python</title><content type='html'>I've blogged &lt;a href="http://pythoneering.blogspot.com/2009/12/what-makes-programming-language-easy-to.html"&gt;previously&lt;/a&gt; about the idea that &lt;b&gt;separation of concerns&lt;/b&gt; is important in making a programming language easy to learn. Dealing with very different concerns using the same language feature is a bad idea because the meaning of symbols then becomes highly context-dependent, making code harder to read. As an example, let's consider the ways in which text and binary data are handled by Java and Python.&lt;br /&gt;&lt;br /&gt;Java got this right from Day One, more or less. In Java, the &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;byte&lt;/span&gt; and &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;char&lt;/span&gt; types are distinctly different, the latter being a 16-bit type supporting Unicode. A slight wrinkle in JDK 1.0 was the fact that I/O was based solely around the byte-oriented &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;a href="http://java.sun.com/javase/6/docs/api/java/io/InputStream.html"&gt;InputStream&lt;/a&gt;&lt;/span&gt; and &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;a href="http://java.sun.com/javase/6/docs/api/java/io/OutputStream.html"&gt;OutputStream&lt;/a&gt;&lt;/span&gt; class hierarchies, but this was fixed in JDK 1.1 via the introduction of parallel, text-oriented class hierarchies based on&amp;nbsp;&lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;a href="http://java.sun.com/javase/6/docs/api/java/io/Reader.html"&gt;Reader&lt;/a&gt;&lt;/span&gt; and &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;a href="http://java.sun.com/javase/6/docs/api/java/io/Writer.html"&gt;Writer&lt;/a&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;With Python, things have been rather different. Python predates both Java and the &lt;a href="http://www.unicode.org/history/versionone.html"&gt;finalised Unicode 1.0 standard&lt;/a&gt;, so for a long time it represented text solely as strings of 8-bit ASCII characters. It must have seemed a convenient economy at that time to also use strings as a means of representing sequences of bytes read from a binary file, but this in effect tied the &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;str&lt;/span&gt; type to an 8-bit character representation. When it eventually became necessary (in 2000) for Python to support Unicode, the only way that this could be achieved without breaking existing code was to introduce a new &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;unicode&lt;/span&gt; type for Unicode-based strings.&lt;br /&gt;&lt;br /&gt;The upshot of all this was that Python now had two &lt;i&gt;overlapping&lt;/i&gt; types: &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;str&lt;/span&gt;, to represent ASCII text and binary data; and &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;unicode&lt;/span&gt;, to represent Unicode text.&lt;br /&gt;&lt;br /&gt;Aside from the problem of not keeping the different concerns of text and binary data separate, this solution also demonstrates undesirable redundancy; ideally, there should be just one way of representing text.&lt;br /&gt;&lt;br /&gt;Perhaps the most significant improvement made in Python 3 is the reimplementation of &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;str&lt;/span&gt; as a Unicode-based type and the inclusion of an entirely separate &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;bytes&lt;/span&gt; type for representing byte sequences. Nothing is lost in this more orthogonal scheme, thanks to the provision of an &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;encode&lt;/span&gt; method in &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;str&lt;/span&gt; that converts a string to the equivalent &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;bytes&lt;/span&gt; object and a decode method in &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;bytes&lt;/span&gt; that converts a byte sequence to the equivalent string - given an appropriate codec in each case, of course.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-1348707834637304507?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/1348707834637304507/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/separation-of-concerns-in-java-and.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/1348707834637304507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/1348707834637304507'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/separation-of-concerns-in-java-and.html' title='Separation of concerns in Java and Python'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-6221048931649324576</id><published>2009-12-17T14:07:00.009Z</published><updated>2009-12-18T10:31:15.733Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Minimal redundancy in Java and Python (2)</title><content type='html'>Following on from &lt;a href="http://pythoneering.blogspot.com/2009/12/minimal-redundancy-in-java-and-python-1.html"&gt;Part 1&lt;/a&gt; of this discussion, let's consider some more examples of minimal redundancy (or the lack thereof) in the Java and Python programming languages.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Integer Representation&lt;/h3&gt;&lt;br /&gt;The C &amp;amp; C++ languages support eight different primitive integer representations: ten if you include &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;char&lt;/span&gt; and &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;unsigned char&lt;/span&gt;.  Java has only four primitive integer types (lacking the unsigned types of C &amp;amp; C++) but also has wrapper classes for each of these, plus a &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="http://java.sun.com/javase/6/docs/api/java/math/BigInteger.html"&gt;BigInteger&lt;/a&gt;&lt;/span&gt; class for representing arbitrary-precision integers - giving a grand total of nine representations. There is too much choice here for the novice programmer, for whom considerations of optimisation and efficient memory usage are unimportant compared with the business of learning the fundamentals of programming.&lt;br /&gt;&lt;br /&gt;Python has historically provided only two representations: an &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;int&lt;/span&gt; type equivalent to the &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;long&lt;/span&gt; of Java, C and C++; and a &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;long&lt;/span&gt; type similar to Java's &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;BigInteger&lt;/span&gt;. Whilst two is certainly a big improvement on nine, there is still unnecessary redundancy here. The distinction between arbitrary-precision and fixed-length integer representations and the notion that CPU support makes the latter more efficient are worthy of discussion, certainly, but I would argue that such issues fall outside the scope of an introductory programming course.&lt;br /&gt;&lt;br /&gt;Python 3 removes the redundancy completely by having a &lt;b&gt;single integer type&lt;/b&gt;, complementing its single floating-point type.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Console I/O&lt;/h3&gt;&lt;br /&gt;It is common in introductory programming courses to use the console for input and output. Simple output has always been straightforward in Java, courtesy of &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;System.out.println&lt;/span&gt;, but the language has yet to acquire a correspondingly simple &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;System.in.readln&lt;/span&gt; method.  Java SE 6 was the first release to improve console I/O significantly, via a &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="http://java.sun.com/javase/6/docs/api/java/io/Console.html"&gt;Console&lt;/a&gt;&lt;/span&gt; class proving &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;printf&lt;/span&gt; and &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;readLine&lt;/span&gt; methods.&lt;br /&gt;&lt;br /&gt;Python has also suffered from a lack of symmetry in its support for console I/O, albeit of a more subtle kind. Consider, for example, a simple program to greet its user by name:&lt;br /&gt;&lt;pre class="brush: python"&gt;name = raw_input('Who are you? ')&lt;br /&gt;print 'Hello', name&lt;br /&gt;&lt;/pre&gt;Can you spot the conceptual redundancy in this code? Console input is handled with a function call, but console output involves a print &lt;i&gt;statement&lt;/i&gt;.  Two distinctly different concepts are being used here, when one would do.  Fortunately, Python 3 corrects the design oversight by making &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;print&lt;/span&gt; a function.&lt;br /&gt;&lt;br /&gt;I have to admit, I wasn't particularly convinced that this was a problem until a student asked me for help one day during a lab class. The exercise involved writing a program to convert a temperature from the Celsius scale to the Fahrenheit scale, and his solution, written for Python 2.5, looked something like this:&lt;br /&gt;&lt;pre class="brush: python"&gt;ctemp = float(raw_input('Enter temperature in Celsius: '))&lt;br /&gt;ftemp = 9.0*ctemp / 5 + 32&lt;br /&gt;print(ctemp, 'deg. C', is, ftemp, 'deg. F')&lt;br /&gt;&lt;/pre&gt;His question was quite simple: "Can you tell me how to get rid of the brackets and commas in the output?" Having written a function call to handle data input, he must have temporarily forgotten the syntax for printing and assumed, reasonably enough, that it would be handled symmetrically by Python, i.e. as a function call; instead, he ended up constructing a tuple by accident and passing it to the &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;print&lt;/span&gt; statement! He might have realised his error, but for the fact that we hadn't yet discussed tuples at that point in the course...  Thankfully, such confusion cannot arise in Python 3.&lt;br /&gt;&lt;br /&gt;You may have noticed the occurrence of &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;raw_input&lt;/span&gt; in the two preceding code examples and perhaps wondered why the more obvious-sounding built-in function &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;input&lt;/span&gt; isn't being used instead. It turns out that the latter can cause nasty surprises for novices, as I'll discuss in another post. For now, I'll simply point out that this is another example of redundancy in Python. The &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;input&lt;/span&gt; function is entirely unnecessary, given that its behaviour can be duplicated by combining another built-in function, &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;eval&lt;/span&gt;, with &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;raw_input&lt;/span&gt;. Python 3 fixes things by having a single function called &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;input&lt;/span&gt; that behaves just like the old &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;raw_input&lt;/span&gt; function.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Object-Oriented Programming&lt;/h3&gt;&lt;br /&gt;There is no redundancy to speak of in Java's object model. True, it gives us concrete classes, abstract classes and interfaces, but these things are distinctly different from each other. (The fact that Java forbids multiple inheritance means that a purely abstract class is not equivalent to an interface, for example.)&lt;br /&gt;&lt;br /&gt;Things have not been so clear-cut in Python, due to the way in which Python's object model has evolved. Before Python 2.2 arrived in December 2001, there were significant differences between Python's built-in types and user-defined classes, such that it was impossible to create a user-defined subclass of a built-in type. Version 2.2 went a long way towards healing the class/type split by introducing &lt;b&gt;new-style classes&lt;/b&gt; alongside the existing &lt;b&gt;classic classes&lt;/b&gt;, and by turning most of the built-in types into these new-style classes. Since version 2.2, it has therefore been possible to begin class definitions in two ways:&lt;br /&gt;&lt;pre class="brush: python"&gt;# Old-style&lt;br /&gt;class Foo:&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;# New-style&lt;br /&gt;class Foo(object):&lt;br /&gt;    ...&lt;br /&gt;&lt;/pre&gt;Students often fail to recognise that these examples are two different kinds of class. This could be a particular problem for those coming to Python from Java, where &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;class Foo&lt;/span&gt; and &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;class Foo extends Object&lt;/span&gt; are entirely equivalent ways of beginning a class definition.&lt;br /&gt;&lt;br /&gt;Unfortunately, many of the books and online tutorials on Python published since the release of version 2.2 have done little to clarify the distinction between old- and new-style classes or provide adequate guidance to novice programmers on which kind of class should be used. Some (e.g., &lt;a href="http://www.wrox.com/WileyCDA/WroxTitle/Beginning-Python.productCd-0764596543.html"&gt;Norton et al&lt;/a&gt;, &lt;a href="http://oreilly.com/catalog/9780596009250/"&gt;Lutz&lt;/a&gt;) have ignored new-style classes altogether whilst others (e.g., &lt;a href="http://www.pythonforrookies.org/"&gt;Mount et al&lt;/a&gt;) have acknowledged their existence but used old-style classes almost exclusively in example code. In some cases (e.g., &lt;a href="http://www.apress.com/book/view/9781590595190"&gt;Hetland&lt;/a&gt;) there is a balanced discussion of the two class types and a few titles (e.g., &lt;a href="http://corepython.com/"&gt;Chun&lt;/a&gt;, &lt;a href="http://books.google.com/books?id=754knV_fyf8C&amp;amp;printsec=frontcover&amp;amp;dq=telles+%22python+power%22&amp;amp;ei=0iUqS7vJJ6bMzQSxzajbBA&amp;amp;cd=1#v=onepage&amp;amp;q=&amp;amp;f=false"&gt;Telles&lt;/a&gt;) have encouraged a more modern approach by concentrating almost exclusively on new-style classes. This lack of consistency can be very confusing for students.&lt;br /&gt;&lt;br /&gt;Python 3 solves the problem by removing old-style classes entirely, leaving us with a single object model based on new-style classes. In Python 3, class definitions start off much as they did before, but with the essential difference that &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;object&lt;/span&gt; is &lt;i&gt;implicitly&lt;/i&gt; a superclass (as is the case in Java and C#). Thus, there is no longer any difference between the two styles of class definition shown above.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-6221048931649324576?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/6221048931649324576/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/minimal-redundancy-in-java-and-python-2.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6221048931649324576'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6221048931649324576'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/minimal-redundancy-in-java-and-python-2.html' title='Minimal redundancy in Java and Python (2)'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-6093142812734998715</id><published>2009-12-17T08:18:00.001Z</published><updated>2009-12-17T09:56:15.045Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Minimal redundancy in Java and Python (1)</title><content type='html'>I've blogged &lt;a href="http://pythoneering.blogspot.com/2009/12/what-makes-programming-language-easy-to.html"&gt;previously&lt;/a&gt; about the idea that &lt;b&gt;minimal redundancy&lt;/b&gt; is important in making a programming language easy to learn; in essence, a language should avoid providing multiple, redundant ways of achieving the same goal. In this post, I'll present an example of how Java and Python compare when evaluated according to this principle.&lt;br /&gt;&lt;br /&gt;Let's consider the concept of &lt;b&gt;iteration through a sequence of things&lt;/b&gt;. In Java, the syntax required to implement this concept varies considerably, depending on the type of sequence being handled and the version of Java that we happen to be using. For example, if we wish to iterate through the characters of a string, printing each one on the console, we would accomplish this with code such as&lt;br /&gt;&lt;pre class="brush: java"&gt;for (int i = 0; i &amp;lt; message.length(); ++i) {&lt;br /&gt;  System.out.println(message.charAt(i));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The equivalent approach to indexing characters in an array is a little different, with &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;length&lt;/span&gt; being an attribute of the array rather than a method call and square brackets being used in place of the &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;charAt&lt;/span&gt; method: &lt;br /&gt;&lt;pre class="brush: java"&gt;for (int i = 0; i &amp;lt; messageChars.length; ++i) {&lt;br /&gt;  System.out.println(messageChars[i]);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The equivalent &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;for&lt;/span&gt; loop for iterating through a &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="http://java.sun.com/javase/6/docs/api/java/util/Vector.html"&gt;Vector&lt;/a&gt;&lt;/span&gt; of objects such as integers is again subtly different; indeed, it can be written in two ways - either using the old syntax prevalent before the appearance of the Collections framework in JDK 1.2 or using the alternative &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;get&lt;/span&gt; method call that was added to bring the &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Vector&lt;/span&gt; class into line with other containers from the Collections framework:&lt;br /&gt;&lt;pre class="brush: java"&gt;for (int i = 0; i &amp;lt; vec.size(); ++i) {&lt;br /&gt;  System.out.println(vec.elementAt(i));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;for (int i = 0; i &amp;lt; vec.size(); ++i) {&lt;br /&gt;  System.out.println(vec.get(i));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Of course, it is also possible to enumerate items in a &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Vector&lt;/span&gt; one at a time rather than indexing them, but yet again there is more than one approach to this. For example, we can use the &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="http://java.sun.com/javase/6/docs/api/java/util/Enumeration.html"&gt;Enumeration&lt;/a&gt;&lt;/span&gt; interface that predates JDK 1.2 or we can use the &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;a href="http://java.sun.com/javase/6/docs/api/java/util/Iterator.html"&gt;Iterator&lt;/a&gt;&lt;/span&gt; interface introduced with the Collections framework:&lt;br /&gt;&lt;pre class="brush: java"&gt;Enumeration&amp;lt;Integer&amp;gt; enumerator = vec.elements();&lt;br /&gt;while (enumerator.hasMoreElements()) {&lt;br /&gt;  System.out.println(enumerator.nextElement());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Iterator&amp;lt;Integer&amp;gt; iterator = vec.iterator();&lt;br /&gt;while (iterator.hasNext()) {&lt;br /&gt;  System.out.println(iterator.next());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Admittedly, JDK 1.5 helped the Java programmer by introducing a 'for each' loop syntax that greatly simplifies the &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Vector&lt;/span&gt; enumeration examples above and can even be used to enumerate array elements:&lt;br /&gt;&lt;pre class="brush: java"&gt;for (int number : vec) {&lt;br /&gt;  System.out.println(number);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;for (char character : messageChars) {&lt;br /&gt;  System.out.println(character);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Useful though this undoubtedly is, it has yet to replace the older approaches as the obvious way to do things; all of those older approaches are still viable in Java, and continue to be described in textbooks and online tutorials.&lt;br /&gt;&lt;br /&gt;Now consider a text file. This can be regarded as a sequence of lines, and Java provides a couple of obvious ways of reading such a sequence - but, unfortunately, the syntax is different yet again from the examples shown earlier:&lt;br /&gt;&lt;pre class="brush: java"&gt;// Before JDK 1.5&lt;br /&gt;BufferedReader inputFile = new BufferedReader(new FileReader("foo.txt"));&lt;br /&gt;String line = inputFile.readLine();&lt;br /&gt;while (line != null) {&lt;br /&gt;  System.out.println(line);&lt;br /&gt;  line = inputFile.readLine();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Since JDK 1.5&lt;br /&gt;Scanner inputFile = new Scanner(new File("foo.txt"));&lt;br /&gt;while (inputFile.hasNextLine()) {&lt;br /&gt;  System.out.println(inputFile.nextLine());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We can summarise the preceding arguments by saying that characters in a string, objects in a container and lines in a file are all examples of a sequence of things, but Java requires different iteration syntax in each case. To make matters worse, in two of the three cases there are multiple options available!&lt;br /&gt;&lt;br /&gt;Python is vastly simpler in comparison, supporting each of these scenarios with one obvious, consistent syntax:&lt;br /&gt;&lt;pre class="brush: python"&gt;for character in string:&lt;br /&gt;    print character&lt;br /&gt;&lt;br /&gt;for number in numbers:&lt;br /&gt;    print number&lt;br /&gt;&lt;br /&gt;input_file = open('foo.txt')&lt;br /&gt;for line in input_file:&lt;br /&gt;    print line,&lt;br /&gt;&lt;/pre&gt;True, we could also write these examples using &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;while&lt;/span&gt; loops, &lt;i&gt;but that would be a very obviously inferior way of doing things&lt;/i&gt; - so much so that I've never seen it advocated in any book or online tutorial on Python programming.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-6093142812734998715?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/6093142812734998715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/minimal-redundancy-in-java-and-python-1.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6093142812734998715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6093142812734998715'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/minimal-redundancy-in-java-and-python-1.html' title='Minimal redundancy in Java and Python (1)'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-4963955640236851148</id><published>2009-12-16T10:03:00.006Z</published><updated>2009-12-16T14:37:11.635Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>What makes a programming language easy to learn?</title><content type='html'>This is something that I've been thinking about for a while. &amp;nbsp;I can't claim to have any deep insights or to have conducted any rigorous research, but intuition plus the anecdotal evidence from over twelve years of teaching programming to undergraduates leads me to suggest four principles that a language should follow:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Minimal redundancy&lt;/li&gt;&lt;li&gt;Separation of concerns&lt;/li&gt;&lt;li&gt;Minimal surprise&lt;/li&gt;&lt;li&gt;Appropriate complexity&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Minimal redundancy&lt;/b&gt; essentially means that a language should avoid having many similar ways of achieving a particular goal - interestingly, the opposite of the well-known Perl mantra &lt;a href="http://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it"&gt;"There's More Than One Way To Do It"&lt;/a&gt;.  Having unnecessary, redundant features means that there is more for students to learn, for little material benefit.  Teaching only a subset of the language won't help matters, because students will inevitably come across the features you omit via other sources such as textbooks, websites found via Google, etc - and this creates uncertainty as to which is the 'best' way to do something.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Separation of concerns&lt;/b&gt; is the counterbalance to minimal redundancy. &amp;nbsp;Whereas it is desirable for a language to keep syntax and features to a minimum, this should not be done to the extent that very different concerns are dealt with using the same syntax or language feature.  In essence, a language should avoid overloading its syntax with different, context-dependent meanings if possible, because this can cause unnecessary confusion, make code harder to read, etc.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Minimal surprise&lt;/b&gt; means that, where possible, a language should behave in a manner consistent with the normal expectations of the novice programmer. &amp;nbsp;Surprising behaviour forces the learner to expend extra mental effort to process and understand what they are seeing; furthermore, it can have a detrimental effect on programmer confidence.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Appropriate complexity&lt;/b&gt;&amp;nbsp;means that small, simple tasks should be achievable with small, simple programs; moreover, small increases in the size and complexity of a task should result in correspondingly small increases in program size and complexity.&lt;br /&gt;&lt;br /&gt;In forthcoming blog posts, I'll expand on each of these principles and give examples of how well Python conforms to them in comparison with another language that is used in higher education :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-4963955640236851148?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/4963955640236851148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/what-makes-programming-language-easy-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4963955640236851148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/4963955640236851148'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/what-makes-programming-language-easy-to.html' title='What makes a programming language easy to learn?'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-6654207053907225234</id><published>2009-12-15T13:03:00.003Z</published><updated>2009-12-15T19:19:59.292Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='django'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><title type='text'>System usage monitoring with Django</title><content type='html'>I haven't blogged about &lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt; in a long while - partly because I've been too busy doing other things, such as using it to create a real web application (as opposed to the personal web apps and teaching apps that I'd previously written).&lt;br /&gt;&lt;br /&gt;The real web application in question is a system to analyse usage of a commercial virtual learning environment (VLE) deployed at a higher education institution.&amp;nbsp; This VLE is large and heavily used, as the following stats from the 2008-9 academic year indicate:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; 30,000+ users&lt;br /&gt;&amp;nbsp; 258 million hits against web server&lt;br /&gt;&amp;nbsp; 1.9 million logins from students&lt;br /&gt;&amp;nbsp; Average of 6,200 logins per day, (peaking at 20,000)&lt;br /&gt;&lt;br /&gt;Our system is able to determine the type of student that has logged into the VLE.&amp;nbsp; It also uses built-in knowledge of the local network plus &lt;a href="http://www.maxmind.com/app/geolitecountry"&gt;GeoIP&lt;/a&gt; data to identify where logins are coming from.&amp;nbsp; Information on the time and location of login and type of student are stored in a database, and Django is used to provide a web-based interface to this database.&amp;nbsp; The results of queries are presented to the user in various forms - typically as tabular data (paginated if necessary) plus a chart of some sort if appropriate.&amp;nbsp; We use &lt;a href="http://matplotlib.sourceforge.net/"&gt;matplotlib&lt;/a&gt; to generate pie charts, bar charts and time series charts, plus the &lt;a href="http://code.google.com/apis/chart/"&gt;Google Chart API &lt;/a&gt;to produce maps showing the countries from which students are accessing the VLE when they are away from university.&lt;br /&gt;&lt;br /&gt;In future blog posts, I'll go into more detail about how it all works...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-6654207053907225234?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/6654207053907225234/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/i-havent-blogged-about-django-in-long.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6654207053907225234'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/6654207053907225234'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/i-havent-blogged-about-django-in-long.html' title='System usage monitoring with Django'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-457490552409775700</id><published>2009-12-12T11:54:00.001Z</published><updated>2009-12-15T15:54:49.338Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='geolocation'/><category scheme='http://www.blogger.com/atom/ns#' term='visualisation'/><category scheme='http://www.blogger.com/atom/ns#' term='teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='intrusion'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>The one that wasn't a game...</title><content type='html'>Following on from yesterday's post about the recent graphics programming assignment done by my first-year students, it is worth noting that one of our students was adventurous enough to implement something other than a game.&lt;br /&gt;&lt;br /&gt;Alex Hawdon wrote a very interesting program that invokes &lt;a href="http://lcamtuf.coredump.cx/p0f.shtml"&gt;p0f&lt;/a&gt; to analyse incoming attempts to establish TCP connections with your machine, interprets IP addresses using a &lt;a href="http://www.maxmind.com/app/geolitecity"&gt;GeoIP&lt;/a&gt; database and then serves up the results as a &lt;a href="http://en.wikipedia.org/wiki/Keyhole_Markup_Language"&gt;KML&lt;/a&gt; file over HTTP - the latter then being monitored via &lt;a href="http://earth.google.co.uk/"&gt;Google Earth&lt;/a&gt;, of course.&amp;nbsp; The net result: a 3D, real-time visualisation of attempted hacks against your machine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-457490552409775700?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/457490552409775700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/one-that-wasnt-game.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/457490552409775700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/457490552409775700'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/one-that-wasnt-game.html' title='The one that wasn&apos;t a game...'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-2048333205245215128</id><published>2009-12-11T12:41:00.002Z</published><updated>2009-12-12T11:24:33.616Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='pygame'/><category scheme='http://www.blogger.com/atom/ns#' term='teaching'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Game Demos</title><content type='html'>Yesterday was the demonstration session for our open-ended graphics programming coursework.&amp;nbsp; The students seemed to enjoy themselves - even to the point of turning up in suitably festive clothing:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_36V6kpTPt8E/SyIq9qVz4NI/AAAAAAAAAvc/TL_blI-Ht4k/s1600-h/cwk2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_36V6kpTPt8E/SyIq9qVz4NI/AAAAAAAAAvc/TL_blI-Ht4k/s320/cwk2.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The aim of the whole exercise was to develop something in Python that involved &lt;b&gt;dynamic graphics&lt;/b&gt;.  We didn't require it to be a game, but almost everyone chose this option - probably because we devoted several lectures and one of the lab classes to explaining how &lt;a href="http://www.pygame.org/"&gt;Pygame&lt;/a&gt; could be used for this!&lt;br /&gt;&lt;br /&gt;There were some very impressive submissions.&amp;nbsp; &lt;b&gt;Ian Kernick&lt;/b&gt; (pictured above) and &lt;b&gt;Sean Watson&lt;/b&gt; - the self-styled 'S &amp;amp; I Productions' - gave us &lt;i&gt;Nazi Zombies&lt;/i&gt;: a third-person shooter with suitably gory graphics and sound effects.&amp;nbsp; So polished was this piece of work that it even had its own movie intro!&amp;nbsp; One notable feature was the layering of sprites to create a pseudo-3D effect in which the player could move behind or in front of the zombies.&lt;br /&gt;&lt;br /&gt;Zombies were also the main enemy faced by the player in &lt;b&gt;Alex Hawes&lt;/b&gt;' game, but this time the player was moved around using an XBox 360 game controller.&amp;nbsp; &lt;b&gt;Ed Worthy&lt;/b&gt; used a similar control mechanism in his Geometry Wars clone - all the more impressive for being apparently implemented from scratch in a marathon all-night programming session right before the deadline!&amp;nbsp; I'd love to see what he could have done with better time management...&lt;br /&gt;&lt;br /&gt;There was plenty of other good work on display.&amp;nbsp; &lt;b&gt;Julie Tillier&lt;/b&gt; showed us a very complete and playable PacMan-style maze game and &lt;b&gt;Minos Galanakis&lt;/b&gt; demoed a ballistics game in which the player controlled the angle and speed of a projectile fired from a cannon.&amp;nbsp; Projectile motion was governed by realistic physics and the player's score was synchronised with a high-score table stored externally on an FTP server.&lt;br /&gt;&lt;br /&gt;It was common for students to take their inspiration from existing, often very familiar games.&amp;nbsp; In addition to those examples mentioned above, we saw a decent effort at implementing a Guitar Hero clone (driven by key presses rather than the authentic guitar-shaped controller, regrettably) and also a Frogger-style game called &lt;i&gt;Intoxication&lt;/i&gt;, in which the protagonist was a student evading heavy traffic to drink pints of beer that appeared randomly at the roadside!&amp;nbsp; Hmm...&lt;br /&gt;&lt;br /&gt;We rather liked an unusual-looking game from &lt;b&gt;Stefan Piazza&lt;/b&gt; and &lt;b&gt;John Lau&lt;/b&gt;, called &lt;i&gt;Bit Defence&lt;/i&gt;.&amp;nbsp; It had colourful, distinctive vector-style graphics and was notable for being a two-player game, with multiple levels and power-ups.&amp;nbsp; The player-controlled sprites had to orbit around a central disc-shaped zone that they were defending, as well as rotating so that they were always facing outwards.&amp;nbsp; A lot of thought had clearly gone into how this motion could be smoothly and efficiently animated.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_36V6kpTPt8E/SyI7__yhekI/AAAAAAAAAvk/kh3TwFbzJBc/s1600-h/bd1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_36V6kpTPt8E/SyI7__yhekI/AAAAAAAAAvk/kh3TwFbzJBc/s200/bd1.jpg" /&gt;&lt;/a&gt;&lt;a href="http://4.bp.blogspot.com/_36V6kpTPt8E/SyI8fprF7rI/AAAAAAAAAvs/REvYFYVYOhM/s1600-h/bd2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_36V6kpTPt8E/SyI8fprF7rI/AAAAAAAAAvs/REvYFYVYOhM/s200/bd2.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-2048333205245215128?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/2048333205245215128/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/game-demos.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2048333205245215128'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2048333205245215128'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/game-demos.html' title='Game Demos'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_36V6kpTPt8E/SyIq9qVz4NI/AAAAAAAAAvc/TL_blI-Ht4k/s72-c/cwk2.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-9198945171753692907</id><published>2009-12-05T11:16:00.001Z</published><updated>2009-12-11T13:49:12.597Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='opensource'/><title type='text'>Python's Moratorium</title><content type='html'>Jesse Noller has posted a &lt;a href="http://jessenoller.com/2009/12/04/pythons-moratorium-lets-think-about-this/"&gt;thorough and well-reasoned explanation&lt;/a&gt; of Python's recently-announced &lt;a href="http://www.python.org/dev/peps/pep-3003/"&gt;moratorium on new language features&lt;/a&gt;.&amp;nbsp; I'm surprised that people are grumbling about the moratorium, but it is good to see a well-argued response to the critics.&lt;br /&gt;&lt;br /&gt;I'm very keen for us to standardise on Python 3.x in our teaching at Leeds, but the (understandably) slow pace of transition to the new syntax for some of the large third-party packages and frameworks that we use (e.g., Pygame, wxPython, etc) has meant that we've been reluctant up until now to make the commitment.&amp;nbsp; My hope is that we'll see greater enthusiasm for making the '2 to 3' transition, now that Python is not going to be a moving target for the next couple of years.&lt;br /&gt;&lt;br /&gt;Of course, this is a community where we should all pitch in and help to make change happen - so I'm not going to sit back and wait for others to do all the work.&amp;nbsp; I just have to figure out where I can make an effective and useful contribution...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-9198945171753692907?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/9198945171753692907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/12/jesse-noller-has-posted-thorough-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/9198945171753692907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/9198945171753692907'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/12/jesse-noller-has-posted-thorough-and.html' title='Python&apos;s Moratorium'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-3405591777456921774</id><published>2009-11-26T23:43:00.000Z</published><updated>2009-11-26T23:47:13.161Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='karmic'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Eclipse on Karmic</title><content type='html'>Couldn't figure out why an install of Eclipse SDK 3.5.1 onto my now Karmic-enabled laptop wasn't running correctly, and then a few minutes of googling led me to &lt;a href="http://www.norio.be/blog/2009/10/problems-eclipse-buttons-ubuntu-910"&gt;this very useful tip&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-3405591777456921774?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/3405591777456921774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/11/eclipse-on-karmic.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/3405591777456921774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/3405591777456921774'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/11/eclipse-on-karmic.html' title='Eclipse on Karmic'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-451296215405131174</id><published>2009-11-26T09:08:00.008Z</published><updated>2009-12-02T17:40:05.296Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='laptop'/><category scheme='http://www.blogger.com/atom/ns#' term='dell'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='mouse'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Banishing the Drifting Pointer</title><content type='html'>A well-known problem with Dell Latitude laptops such as the D800 concerns the mouse pointer, which can start drifting across the screen of its own accord, for no apparent reason.&lt;br /&gt;&lt;br /&gt;The cause of the problem is the small thumbstick embedded in the keyboard.  Under Windows XP, I had applied the simple fix of disabling the stick in the mouse preferences dialog, but when I upgraded my D800 to Ubuntu 9.10 the other day, the problem reappeared - and there was no handy option in System Preferences to correct the issue.&lt;br /&gt;&lt;br /&gt;Some blogs advocate the drastic step of &lt;a href="http://gimbo.org.uk/blog/2005/11/12/fixing-mouse-drift-on-a-dell-latitude-c600-with-a-sledgehammer/"&gt;cutting cables inside the machine&lt;/a&gt;, but fortunately I came across a less scary solution in the &lt;a href="http://www.linuxweblog.com/mouse-drift#comment-895"&gt;comment to another blog entry&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Adapting this to my own system, I ended up creating a file &lt;span style="font-family:courier new,courier,monospace;"&gt;/etc/hal/fdi/preprobe/disable.fdi&lt;/span&gt; containing the following:&lt;br /&gt;&lt;pre class="brush: xml"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;deviceinfo version="0.2"&amp;gt;&lt;br /&gt;  &amp;lt;device&amp;gt;&lt;br /&gt;    &amp;lt;match key="input.product" string="DualPoint Stick"&amp;gt;&lt;br /&gt;      &amp;lt;merge key="info.ignore" type="bool"&amp;gt;true&amp;lt;/merge&amp;gt;&lt;br /&gt;    &amp;lt;/match&amp;gt;&lt;br /&gt;  &amp;lt;/device&amp;gt;&lt;br /&gt;&amp;lt;/deviceinfo&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-451296215405131174?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/451296215405131174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/11/banishing-drifting-pointer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/451296215405131174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/451296215405131174'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/11/banishing-drifting-pointer.html' title='Banishing the Drifting Pointer'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-5965982073637334747</id><published>2009-11-25T18:01:00.000Z</published><updated>2009-11-25T18:10:52.237Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='boohewerdine'/><category scheme='http://www.blogger.com/atom/ns#' term='music'/><title type='text'>God Bless The Pretty Things</title><content type='html'>My signed copy of &lt;a href="http://www.boohewerdine.net/"&gt;Boo Hewerdine&lt;/a&gt;'s &lt;a href="http://www.boohewerdine.net/godbless.html"&gt;new album&lt;/a&gt; arrived in the post today, and it's a corker - his best since &lt;span style="font-style: italic;"&gt;Anon&lt;/span&gt;, I think.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.boohewerdine.net/godbless.html"&gt;&lt;img src="http://www.boohewerdine.net/images/artwork/godbless.jpg" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-5965982073637334747?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/5965982073637334747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/11/god-bless-pretty-things.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/5965982073637334747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/5965982073637334747'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/11/god-bless-pretty-things.html' title='God Bless The Pretty Things'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-2883940082415661648</id><published>2009-11-17T14:31:00.000Z</published><updated>2009-11-17T14:41:50.909Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Watershed</title><content type='html'>I've used Linux at home for many years now, starting with SuSE 5-point-something and moving eventually to Ubuntu at around the time of the 'Gutsy' release.  I've tended to upgrade every 12-18 months, and each time I've installed from scratch.  The install experience has improved gradually with time, each successive upgrade causing fewer problems, but this weekend was something of a watershed: my first completely problem-free Linux install.  Everything just worked - even sound, traditionally the thing that has always caused me grief in the past.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-2883940082415661648?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/2883940082415661648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/11/watershed.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2883940082415661648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2883940082415661648'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/11/watershed.html' title='Watershed'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3748499357064620349.post-2556929327839123146</id><published>2009-11-10T13:35:00.001Z</published><updated>2009-11-10T13:59:49.400Z</updated><title type='text'>A new beginning</title><content type='html'>Managing a blog on my own server was becoming a chore for various reasons, so I've decided to experiment with an externally-hosted solution.  This is also an opportunity to try out a different service (Blogger rather than Wordpress).  So far so good...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3748499357064620349-2556929327839123146?l=pythoneering.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythoneering.blogspot.com/feeds/2556929327839123146/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pythoneering.blogspot.com/2009/11/new-beginning.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2556929327839123146'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3748499357064620349/posts/default/2556929327839123146'/><link rel='alternate' type='text/html' href='http://pythoneering.blogspot.com/2009/11/new-beginning.html' title='A new beginning'/><author><name>Nick</name><uri>http://www.blogger.com/profile/07105795041340396458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_36V6kpTPt8E/SYcC2U0ZW5I/AAAAAAAAAbA/z-415bP1n6w/S220/pythoneer1.jpg'/></author><thr:total>0</thr:total></entry></feed>
