<?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-7085952916595348171</id><updated>2012-02-16T18:18:43.567-08:00</updated><category term='Python'/><category term='regex'/><category term='vi'/><category term='list comprehensions'/><category term='performance'/><category term='vim'/><category term='editors'/><category term='Tkinter'/><category term='timing'/><category term='tokenizer'/><category term='wxPython'/><category term='wxWidgets'/><category term='GUI'/><title type='text'>bondgeek's python adventures</title><subtitle type='html'>'''
a blog about using python
'''</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-8635964387122251090</id><published>2009-08-13T22:46:00.001-07:00</published><updated>2009-08-13T22:46:10.568-07:00</updated><title type='text'>best blog ever</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;a href='http://johnaugust.com/'&gt;johnaugust.com&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Has nothing to do with quantitative finance or technology--it's about screenwriting.  But it's very well written (no surprise) and, most strikingly, reading the comments doesn't reinforce my most cynical  humanity the way most blogs do&lt;br/&gt;&lt;br/&gt;&lt;blockquote/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=d745eb04-5b1c-8d22-8f4a-ca389ee1e56a' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-8635964387122251090?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/8635964387122251090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/08/best-blog-ever_13.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/8635964387122251090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/8635964387122251090'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/08/best-blog-ever_13.html' title='best blog ever'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-6956998538609646513</id><published>2009-08-13T22:44:00.001-07:00</published><updated>2009-08-13T22:44:06.932-07:00</updated><title type='text'>best blog ever</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;a href='http://johnaugust.com/'&gt;johnaugust.com&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Has nothing to do with quantitative finance or technology--it's about screenwriting.  But it's very well written (no surprise) and, most strikingly, reading the comments doesn't reinforce my most cynical feelings for humanity the way most blogs do.&lt;br/&gt;&lt;br/&gt;&lt;blockquote/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=11352ea9-69bb-8caf-a36b-b7ac0f92c527' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-6956998538609646513?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/6956998538609646513/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/08/best-blog-ever.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/6956998538609646513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/6956998538609646513'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/08/best-blog-ever.html' title='best blog ever'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-5072844636970978547</id><published>2009-08-06T07:39:00.001-07:00</published><updated>2009-08-06T07:45:30.682-07:00</updated><title type='text'>Dear Steve,</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;MEMORANDUM--HIGHLY CONFIDENTIAL&lt;br/&gt;&lt;br/&gt;To:  Steve Jobs&lt;br/&gt;&lt;br/&gt;From:  bondgeek&lt;br/&gt;&lt;br/&gt;Date: August 6th, 2009&lt;br/&gt;&lt;br/&gt;re:  &lt;a href='http://www.informationweek.com/news/mobility/smart_phones/showArticle.jhtml?articleID=219100117&amp;amp;cid=tab_art_hard_C'&gt;BlackBerry Curve Outsells iPhone 3GS -- Smartphone Sales -- InformationWeek&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Dear Mr. Jobs,&lt;br/&gt;&lt;br/&gt;It's about the email.  True push technology and straight forward synching with corporate email (so what if you're smarter than the Lords of the IT realm at all these major corporations--so is my coffee cup--they control their fiefdoms and you don't--WORK WITH THEM!!!).&lt;br/&gt;&lt;br/&gt;Please let me know if you have any questions.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;blockquote/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=57d2771b-9f64-863c-93af-52322c3d61d7' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-5072844636970978547?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/5072844636970978547/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/08/dear-steve.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/5072844636970978547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/5072844636970978547'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/08/dear-steve.html' title='Dear Steve,'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-5805452929607368346</id><published>2009-07-14T16:07:00.001-07:00</published><updated>2009-07-16T07:35:02.993-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='regex'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='tokenizer'/><title type='text'>RegEx Tokenizer</title><content type='html'>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;The follow code snippet is adapted from Fredrik Lundh's effbot.org entry&lt;br /&gt;&lt;a href="http://effbot.org/zone/xml-scanner.htm"&gt;Using Regular Expressions for Lexical Analysis&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Say you want to tokenize an expression such as "(3+5)*10":&lt;span style="color:#336666;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;small&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#336666;"&gt;#!/usr/bin/env python&lt;br /&gt;'''&lt;br /&gt;Use regex to tokenize a string expression.&lt;br /&gt;adapted from:&lt;br /&gt;http://effbot.org/zone/xml-scanner.htm&lt;br /&gt;'''&lt;br /&gt;import re&lt;br /&gt;&lt;br /&gt;reg_token = re.compile(r"""&lt;br /&gt;    \s*                                #skip whitespace&lt;br /&gt;    ([0-9\.]+|                   #one or more digits or '.'&lt;br /&gt;                                            aka floats or ints&lt;br /&gt;    \w+|                            #words&lt;br /&gt;    [+\-*/!^%&amp;amp;|]{1,2}|  #operators&lt;br /&gt;    .)                                   #any character except newline&lt;br /&gt;    """,&lt;br /&gt;    re.VERBOSE)&lt;br /&gt;&lt;br /&gt;def tokenize(expr):&lt;br /&gt;    '''&lt;br /&gt;    Returns a list of tokens for an expression string.&lt;br /&gt;    Allows operators +-*/!^%&amp;amp;|&lt;br /&gt;    Treats doubled operator e.g., **, ++ as single token&lt;br /&gt;    '''&lt;br /&gt;    def v_token(obj):&lt;br /&gt;        try:&lt;br /&gt;            if '.' in obj:&lt;br /&gt;                return float(obj)&lt;br /&gt;            else:&lt;br /&gt;                return int(obj)&lt;br /&gt;        except:&lt;br /&gt;            return obj&lt;br /&gt;       &lt;br /&gt;    return [v_token(tkn.group()) for tkn&lt;br /&gt;                        in reg_token.finditer(expr)]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;big&gt;Let's test on&lt;/big&gt;&lt;/span&gt;&lt;/small&gt;&lt;span style="color:#000000;"&gt; some expressions&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#336666;"&gt;&lt;small&gt;&lt;br /&gt;expr = ["(3+7)*90",               # basic&lt;br /&gt;        "(3+7.1)*90",                  # has floats&lt;br /&gt;        "(3+7.1)*90*alpha",      # has variables&lt;br /&gt;        "(3+7.1)*90*alpha, g",  # invalid expression, tokenize and leave to parser&lt;br /&gt;        "(5.0 - 3.2)/6*9",            # other forms&lt;br /&gt;        "b = 2 + a*10",&lt;br /&gt;        "x = \n x**2",                   #picks up **, ++ as a token&lt;br /&gt;        "i++",&lt;br /&gt;        ""&lt;br /&gt;        ]&lt;br /&gt;&lt;br /&gt;for exp in expr:&lt;br /&gt;    tkns = tokenize(exp)&lt;br /&gt;    print("\nExpression: %s\nTokens: %s " % (exp, tkns)) &lt;/small&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="color:#336666;"&gt;Gives us...&lt;br /&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color:#336666;"&gt;&lt;small&gt;Expression: (3+7)*90&lt;br /&gt;Tokens: ['(', 3, '+', 7, ')', '*', 90]&lt;br /&gt;&lt;br /&gt;Expression: (3+7.1)*90&lt;br /&gt;Tokens: ['(', 3, '+', 7.0999999999999996, ')', '*', 90]&lt;br /&gt;&lt;br /&gt;Expression: (3+7.1)*90*alpha&lt;br /&gt;Tokens: ['(', 3, '+', 7.0999999999999996, ')', '*', 90, '*', 'a', 'l', 'p', 'h', 'a']&lt;br /&gt;&lt;br /&gt;Expression: (3+7.1)*90*alpha, g&lt;br /&gt;Tokens: ['(', 3, '+', 7.0999999999999996, ')', '*', 90, '*', 'a', 'l', 'p', 'h', 'a', ',', ' g']&lt;br /&gt;&lt;br /&gt;Expression: (5.0 - 3.2)/6*9&lt;br /&gt;Tokens: ['(', 5.0, ' -', 3.2000000000000002, ')', '/', 6, '*', 9]&lt;br /&gt;&lt;br /&gt;Expression: b = 2 + a*10&lt;br /&gt;Tokens: ['b', ' =', 2, ' +', ' a', '*', 10]&lt;br /&gt;&lt;br /&gt;Expression: x =&lt;br /&gt; x**2&lt;br /&gt;Tokens: ['x', ' =', ' \n x', '**', 2]&lt;br /&gt;&lt;br /&gt;Expression: i++&lt;br /&gt;Tokens: ['i', '++']&lt;br /&gt;&lt;br /&gt;Expression:&lt;br /&gt;Tokens: [] &lt;/small&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;a href="http://snippets.dzone.com/user/bondgeek" target="_blank"&gt;code snippet&lt;/a&gt; is at dzone:&lt;a href="http://snippets.dzone.com/user/bondgeek" target="_blank"&gt;  http://snippets.dzone.com/user/bondgeek&lt;/a&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-5805452929607368346?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/5805452929607368346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/07/regex-tokenizer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/5805452929607368346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/5805452929607368346'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/07/regex-tokenizer.html' title='RegEx Tokenizer'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-8031547971966915017</id><published>2009-07-14T09:23:00.001-07:00</published><updated>2009-07-14T09:50:23.528-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vi'/><category scheme='http://www.blogger.com/atom/ns#' term='editors'/><category scheme='http://www.blogger.com/atom/ns#' term='vim'/><title type='text'>Bare Minimum Vim</title><content type='html'>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;blockquote&gt;&lt;span style="font-family:monospace;"&gt;&lt;small&gt;&lt;big&gt;&lt;span style="font-family:sans-serif;"&gt;&lt;b&gt;B&lt;strong&gt;ecause you just can't seem to avoid using it.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/big&gt;&lt;/small&gt;Bare  Minimum Vim&lt;/span&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;/span&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="font-weight: bold;"&gt;v,V&lt;/span&gt;       - visual mode, visual-line mode &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="font-family:monospace;"&gt; (hit ESC to exit)&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;n__&lt;/span&gt;       - prefix a command with a number to repeat 'n' times&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;                E.g., &lt;span style="font-weight: bold;"&gt;5dd&lt;/span&gt; deletes 5 lines&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;Write &amp;amp; Quit = Save &amp;amp; Exit &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;!&lt;/span&gt;        - generally causes a command to ignore changes--see :q!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;:w&lt;/span&gt;       - write the file without exit&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;               &lt;span style="font-weight: bold;"&gt;:w&lt;/span&gt; [filename] - saves to new filename, stays in current buffer&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;               &lt;span style="font-weight: bold;"&gt;:w!&lt;/span&gt; [filename] - overwrites if filename exists&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;:wq&lt;/span&gt;      - write and quit&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;:q&lt;/span&gt;       - quit (fails if there are unsaved changes)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;:q!&lt;/span&gt;      - quit and throw away changes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;Navigation&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;NOTE: lower case treats punctuation as word break&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;[n]G&lt;/span&gt;     - go to line "n", end of file if n omitted&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;e,E&lt;/span&gt;      - jump ahead to end of word &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;b,B&lt;/span&gt;      - jump back to beginning of word&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;w,W&lt;/span&gt;      - jump ahead to start of word&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;0,$&lt;/span&gt;      - jump to start(0) or end($) of line&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;Edits  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;r&lt;/span&gt;        - replace character under cursor&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;x&lt;/span&gt;        - delete character under cursor (places in clipboard)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;dd, dw&lt;/span&gt;   - delete a line, word&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;J        -&lt;/span&gt; Join line below to current line&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;.&lt;/span&gt;        - dot repeats last change&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;u&lt;/span&gt;        - undo last change&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;e!&lt;/span&gt;       - discard changes to last write&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;Insert Mode    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;i,I&lt;/span&gt;      - start insert mode at i=cursor, I=start of line&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;a,A&lt;/span&gt;      - start insert mode after a=cursor, A=end of line&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;Esc&lt;/span&gt;      - exit insert mode&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;Yank &amp;amp; Pull = Cut &amp;amp; Paste&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;yy,yw&lt;/span&gt;    - yank a line, word&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;y$&lt;/span&gt;       - yank to end of line&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;p, P&lt;/span&gt;     - put the clipboard after, before cursor&lt;br /&gt;&lt;br /&gt;Find &amp;amp; Replace&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;/&lt;/span&gt;ptrn    - search forward for pattern, wraps by default&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;?&lt;/span&gt;ptrn    - search backward for pattern&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;n,N&lt;/span&gt;      - repeat in same(n), opposite(N) direction&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;%s/&lt;/span&gt;o&lt;span style="font-weight: bold;"&gt;/&lt;/span&gt;n&lt;span style="font-weight: bold;"&gt;/gc&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;g&lt;/span&gt;&lt;br /&gt;         - global replace old with new with or without confirm&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;Splitting windows &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;Note: Ctrl+w, then the command&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;^w s&lt;/span&gt;    - Split window horizontally&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;^w v&lt;/span&gt;    - Split window vertically&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;^w w&lt;/span&gt;    - switch between windows&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;^w q&lt;/span&gt;    - Quit a window&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;Combo commands&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;ea&lt;/span&gt;    - jump to end of word, then start insert mode after cursor&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;xp&lt;/span&gt;    - delete then paste (transposes characters)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;:wq&lt;/span&gt;    - write then quit&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;Sightly beyond bare minimum&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;:e&lt;/span&gt;     - re-edit current file--e.g, if it has changed on disk&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;:e&lt;/span&gt; [file]    - edit [file] in new buffer &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;ZZ&lt;/span&gt; = :wq&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;ZQ&lt;/span&gt; = :q!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;d&lt;/span&gt;[move]   - delete in direction of arrow movement&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;D&lt;/span&gt;    - delete to end of line&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;R&lt;/span&gt;    - Replace mode, instead of insert&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;~&lt;/span&gt;    - Switch case of character under cursor&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;:r&lt;/span&gt; [file]    - read file, inserting under cursor&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;h,j,k,l&lt;/span&gt;    - Navigate right, down, up,  left&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;    &lt;span style="font-weight: bold;"&gt;()[]{}&lt;/span&gt;    - Navigate by sentence, paragraph, section&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;          E.g. '&lt;span style="font-weight: bold;"&gt;(&lt;/span&gt;' moves 1 sentence backwards, '&lt;span style="font-weight: bold;"&gt;)&lt;/span&gt;' moves forward&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="font-family:sans-serif;"&gt;&lt;em&gt;Some other useful references&lt;/em&gt;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.worldtimzone.com/res/vi.html" target="_blank"&gt;&lt;strong&gt;http://www.worldtimzone.com/res/vi.html&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&lt;br /&gt;&lt;a href="http://www.worldtimzone.com/res/vi.html" target="_blank"&gt;http://www.fprintf.net/vimCheatSheet.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.worldtimzone.com/res/vi.html" target="_blank"&gt;http://jmcpherson.org/editing.html&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt; -- Good place to start if you want to know more, written by somebody who appreciates vim.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-8031547971966915017?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/8031547971966915017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/07/bare-minimum-vim.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/8031547971966915017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/8031547971966915017'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/07/bare-minimum-vim.html' title='Bare Minimum Vim'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-4286666094506132660</id><published>2009-05-28T20:24:00.001-07:00</published><updated>2009-05-28T20:24:18.655-07:00</updated><title type='text'>switch statements in python</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I may as well weight in on the absence of a switch statement in Python, though the topic has been addressed, see:&lt;br/&gt;&lt;br/&gt;&lt;a href='http://www.mustap.com/pythonzone_post_224_python-switch-statement'&gt;Python Zone » Python switch statement&lt;/a&gt;, or&lt;br/&gt;&lt;a href='http://dinomite.net/2008/python-switch-statements-part-2/' target='_blank'&gt;http://dinomite.net/2008/python-switch-statements-part-2&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Here are some examples of switching structures using dictionaries:&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;&lt;small&gt;&lt;font color='#000099'&gt;# switch example 1&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;cases = {&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;'a': &lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;    lambda: 'one',&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;'b':&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;    lambda: 'two',&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;'default':&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;    lambda: 'three'&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;}&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;switch = lambda c: cases.get(c, cases['default'])()&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;var = ['b','xxx']&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;for v in var:&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;    out = switch(v)&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;    print("Switch on %s = %s"%(v,out))&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;# switch example 2&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;op = raw_input("Enter operation for 2 'op' 3: ")&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;if op in "+-*/":&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;    print("2 %s 3 = " % op)&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;else:&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;    print("'%s' is an unkown operation." % op)&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;cases = {&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;     '+': lambda : 2 + 3,&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;     '-': lambda : 2 - 3,&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;     '*': lambda : 2 * 3,&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;     '/': lambda : 2. / 3.&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;     }&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;switch = cases.get(op, lambda : 0)()&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;print(switch)&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;# switch example 3&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;name = raw_input("What is your name? ")&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;op = raw_input("enter 'l' or 'p'")&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;cases = {&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;    'l': len,&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;    'p': lambda txt: txt.upper()&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;    }&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;def default(obj): &lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;    print("Invalid entry, %s" % obj)&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;switch = cases.get(op, default)&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;out = switch(name)&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;print(out)&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;/blockquote&gt;I would say that each of these is as readable as C's switch statement.  I can't say anything for performance, since I haven't run any tests--but Python's dictionaries are fast.   In fact, if I understand the implementation correctly this pattern is pretty much what the switch statement does--set up a hash table (i.e. a dictionary) of test values and choose a code block based on the condition entered.   &lt;br/&gt;&lt;br/&gt;The main argument would be the cumbersomeness of switch on larger blocks of code.  To do that you need to move each block of switch code into a function defined by def.   My only response to that is that if you're writing large blocks of code inside a switch statement, you should think about putting it in a function--in my experience there is usually a fair amount of reused code inside a large switch statement, since the conditions usually each deal with a separate state of a single variable.  Also, the difference in readability between switch and nested if...then..else's diminishes rapidly the larger the conditional code blocks get.&lt;br/&gt;&lt;br/&gt;So, should Python have a switch statement?  Readability of code long term may benefit if there is one way to do a switch as opposed to using different, although similar patterns like above.  But in general, I support keeping control flow logic made of the simplest building blocks--in the long run I think that keeps bloat down and enforces more thinking about the nature of the specific programming problem at hand.&lt;br/&gt;&lt;br/&gt;But if a switch statement was added to Python, I'd probably use it.&lt;br/&gt;&lt;br/&gt;&lt;blockquote/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&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/7085952916595348171-4286666094506132660?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/4286666094506132660/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/05/switch-statements-in-python.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/4286666094506132660'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/4286666094506132660'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/05/switch-statements-in-python.html' title='switch statements in python'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-922334132089525807</id><published>2009-05-13T07:47:00.000-07:00</published><updated>2009-05-13T08:15:36.172-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='list comprehensions'/><category scheme='http://www.blogger.com/atom/ns#' term='timing'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Speaking of timing</title><content type='html'>&lt;span style="font-size:100%;"&gt;Using list comprehension is much faster than not:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;blockquote style="color: rgb(0, 0, 153);"&gt;In [35]: ll = [(x,x*x) for x in range(100)]&lt;br /&gt;&lt;br /&gt;In [36]: def f1(obj):&lt;br /&gt; ....:     for row in obj:&lt;br /&gt; ....:         x = row[0]&lt;br /&gt; ....:         y = row[1]&lt;br /&gt; ....:      &lt;br /&gt;&lt;br /&gt;In [37]: def f2(obj):&lt;br /&gt; ....:     for row in obj:&lt;br /&gt; ....:         x,y = row&lt;br /&gt; ....:      &lt;br /&gt;&lt;br /&gt;In [38]: def f3(obj):&lt;br /&gt; ....:     for row in obj:&lt;br /&gt; ....:         x,y = (row[0],row[1])&lt;br /&gt; ....:      &lt;br /&gt;&lt;br /&gt;In [39]: timing(f1,10000,ll)&lt;br /&gt;f1 2.04&lt;br /&gt;&lt;br /&gt;In [40]: timing(f2,10000,ll)&lt;br /&gt;f2 0.8&lt;br /&gt;&lt;br /&gt;In [41]: timing(f3,10000,ll)&lt;br /&gt;f3 2.41&lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;Function calls always add a bit of overhead:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="color: rgb(0, 0, 153);"&gt;def f1(obj):&lt;br /&gt;     x = min(obj,0.0)&lt;br /&gt;&lt;br /&gt;def f3(obj):&lt;br /&gt;    if obj &lt;= 0.0:&lt;br /&gt;        x = obj&lt;br /&gt;    else:&lt;br /&gt;         x = 0.0&lt;br /&gt;&lt;br /&gt;In [56]: timing(f1,10000,5.)&lt;br /&gt;f1 0.06&lt;br /&gt;&lt;br /&gt;In [57]: timing(f1,10000,-5.)&lt;br /&gt;f1 0.05&lt;br /&gt;&lt;br /&gt;In [67]: timing(f3,10000,5.)&lt;br /&gt;f3 0.04&lt;br /&gt;&lt;br /&gt;In [68]: timing(f3,10000,-5.)&lt;br /&gt;f3 0.04&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Useful to know.&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-922334132089525807?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/922334132089525807/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/05/speaking-of-timing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/922334132089525807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/922334132089525807'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/05/speaking-of-timing.html' title='Speaking of timing'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-348598778437284372</id><published>2009-05-06T10:01:00.001-07:00</published><updated>2009-05-06T10:01:54.017-07:00</updated><title type='text'>Really, they're slow...</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Maybe that previous example isn't fair...after all, I'm treating the value like a list.&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;&lt;small&gt;&lt;font color='#000099'&gt;In [187]: simple = lambda d: d+d&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;In [188]: timing(simple, 100000,dyyyymm)&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;&amp;lt;lambda&amp;gt; 34.84&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;In [189]: simple(dyyyymm)&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;Out[189]: Decimal("4018.10")&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;In [190]: simple(fyyyymm)&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;Out[190]: 4018.0999999999999&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;In [191]: timing(simple, 100000,fyyyymm)&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000099'&gt;&amp;lt;lambda&amp;gt; 0.26&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;/blockquote&gt;&lt;br/&gt;&lt;br/&gt;&lt;blockquote/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=e633cc1d-97ff-861f-8409-b1addb0cd1ba' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-348598778437284372?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/348598778437284372/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/05/really-they-slow.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/348598778437284372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/348598778437284372'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/05/really-they-slow.html' title='Really, they&amp;#39;re slow...'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-599353973646693140</id><published>2009-05-06T09:29:00.001-07:00</published><updated>2009-05-06T09:57:29.289-07:00</updated><title type='text'>Python Decimals are really slow</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;a href='http://docs.python.org/library/decimal.html'&gt;10.4. decimal — Decimal fixed point and floating point arithmetic — Python v2.6.2 documentation&lt;/a&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000066'&gt;&lt;br/&gt;&lt;/font&gt;&lt;/small&gt;&lt;blockquote&gt;&lt;font color='#000066'&gt;&lt;font color='#000099'&gt;&lt;small&gt;In [182]: rparts = lambda d: map(int, (floor(d), round(100*(d%1),0)))&lt;br/&gt;&lt;br/&gt;In [183]: rparts(dyyyymm)&lt;br/&gt;Out[183]: [2009, 5]&lt;br/&gt;&lt;br/&gt;In [184]: rparts(fyyyymm)&lt;br/&gt;Out[184]: [2009, 5]&lt;br/&gt;&lt;br/&gt;In [185]: timing(rparts,10000,dyyyymm)&lt;br/&gt;&amp;lt;lambda&amp;gt; 9.03&lt;br/&gt;&lt;br/&gt;In [186]: timing(rparts,10000,fyyyymm)&lt;br/&gt;&amp;lt;lambda&amp;gt; 0.28&lt;/small&gt;&lt;/font&gt;&lt;br/&gt;&lt;/font&gt;&lt;br/&gt;&lt;/blockquote&gt;Note:  the timing function I'm using here is the same one referred to in an earlier post &lt;a href='http://bgresearch-bondgeek.blogspot.com/2009/04/timing-is-everything.html'&gt;"Timing is everything".&lt;/a&gt;  &lt;br/&gt;&lt;blockquote/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=caa7348a-71cb-836f-90b0-8c8d47c8e079' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-599353973646693140?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/599353973646693140/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/05/python-decimals-are-really-slow.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/599353973646693140'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/599353973646693140'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/05/python-decimals-are-really-slow.html' title='Python Decimals are really slow'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-5090646099792533005</id><published>2009-05-02T10:41:00.001-07:00</published><updated>2009-05-02T10:41:39.029-07:00</updated><title type='text'></title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;a href='http://docs.python.org/library/stdtypes.html#mapping-types-dict'&gt;6. Built-in Types — Python v2.6.2 documentation&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Python variables contain pointers to the data, not the data itself--this one of the more confusing aspects of the language for many.  The implications of this, though, may be made clear by the following example:&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;class mytester(object):&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;    def __init__(self, thingone={}, thingtwo=None):&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;        self.thingone = thingone&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;        if isinstance(thingtwo,dict):&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;            self.thingtwo = thingtwo&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;        else:&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;            self.thingtwo = {}&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;    def setone(self, **kwargs):&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;        self.thingone.update(kwargs)&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;        return self&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;    def settwo(self, **kwargs):&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;        self.thingtwo.update(kwargs)&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;        return self&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;t1 = mytester()&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;t2 = mytester()&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;print(t1.thingone, t2.thingone)&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#336666'&gt;&lt;small&gt;# ({}, {})&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;print(t1.thingtwo, t2.thingtwo)  &lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#336666'&gt;&lt;small&gt;# ({}, {})&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;t1.settwo(say='hi').settwo(to='thing one and thing two') &lt;font color='#000000'&gt;# set thingtwo for t1&lt;/font&gt;&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#336666'&gt;&lt;small&gt;# &amp;lt;__main__.mytester object at 0xecc9d0&amp;gt;&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;print(t1.thingtwo, t2.thingtwo)  &lt;font color='#000000'&gt;# t1 &amp;amp; t2 remain independent&lt;/font&gt;&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#336666'&gt;&lt;small&gt;# ({'to': 'thing one and thing two', 'say': 'hi'}, {})&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;t1.setone(say='hi').setone(to='thing one and thing two') &lt;font color='#000000'&gt;# set thingone for t1&lt;/font&gt; &lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#336666'&gt;&lt;small&gt;# &amp;lt;__main__.mytester object at 0xecc9d0&amp;gt;&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;print(t1.thingone, t2.thingone) &lt;font color='#000000'&gt;# thingone dict points to same object for each&lt;/font&gt;&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#336666'&gt;&lt;small&gt;# ({'to': 'thing one and thing two', 'say': 'hi'}, {'to': 'thing one and thing two', 'say': 'hi'})&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;print id(t1.thingone), id(t2.thingone) &lt;font color='#000000'&gt;#they're the same object!&lt;/font&gt;&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#336666'&gt;&lt;small&gt;# (15704976, 15704976)&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#000099'&gt;&lt;small&gt;print id(t1.thingtwo), id(t2.thingtwo) &lt;font color='#330033'&gt;#they're not!&lt;/font&gt;&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='tahoma' color='#336666'&gt;&lt;small&gt;# (9733440, 9733584)&lt;/small&gt;&lt;/font&gt;&lt;font color='#000099'&gt;&lt;br/&gt;&lt;/font&gt;&lt;br/&gt;&lt;small&gt;&lt;font color='#000000'&gt;In the first instance, the 'thingone' attribute of the class, initializing it with the default '={}' creates a pointer to a dictionary object called 'thingone' (NOT self.thingone).  So, when you change the values in that object for one class, you change them for all.&lt;br/&gt;&lt;br/&gt;One could see where the ability to do this would be useful (say, where you would a singleton pattern in C++, for example).  Still, in general the ability to pass a value to the __init__ method of class implies to the user that the values will be unique for each instance of the class--so the pattern used for 'thingtwo' should be used more often.&lt;br/&gt;&lt;br/&gt;Also, this exercise highlights the importance of the &lt;i&gt;id()&lt;/i&gt; function in Python--it clarifies a lot of things.&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;/blockquote&gt;&lt;blockquote/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=48071bca-d4a0-87ce-9f40-45b7d6271f6f' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-5090646099792533005?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/5090646099792533005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/05/6.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/5090646099792533005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/5090646099792533005'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/05/6.html' title=''/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-5237548726478295929</id><published>2009-04-22T15:33:00.001-07:00</published><updated>2009-04-22T15:34:31.762-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Timing is everything</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;a href='http://www.python.org/doc/essays/list2str/'&gt;Python Patterns - An Optimization Anecdote&lt;/a&gt;&lt;br/&gt;&lt;blockquote&gt;The above link is to an article by Guido van Rossum on the Python website.   Needless to say, anything Guido says on the topic of Python is worth looking at (he is the author of the Python programming language).  &lt;br/&gt;&lt;br/&gt;I thought of this particular article while reading a post, trying to decide how to &lt;a target='_blank' href='http://bytes.com/groups/python/514838-how-test-if-object-sequence-iterable'&gt;check if an object is a sequence&lt;/a&gt;.  While all the contributors to the discussion are helpful, none actually checks the performance of the proposed solutions.  This is typical of the posts you see on various forums.  &lt;br/&gt;&lt;br/&gt;Guido's article highlights how straightforward it is to do basic testing most of the time.  Here is a quick summary of performance of the proposed solutions in the above link:&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;&lt;small&gt;import time&lt;br/&gt;&lt;br/&gt;# Guido's timing function&lt;br/&gt;def timing(f, n, a):&lt;br/&gt;    print f.__name__,&lt;br/&gt;    r = range(n)&lt;br/&gt;    t1 = time.clock()&lt;br/&gt;    for i in r:&lt;br/&gt;        f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a)&lt;br/&gt;    t2 = time.clock()&lt;br/&gt;    print round(t2-t1, 3)&lt;br/&gt;&lt;br/&gt;if __name__ == "__main__":&lt;br/&gt;    #For Example&lt;br/&gt;    # some functions to check if an object is a sequence&lt;br/&gt;    def isit(obj):&lt;br/&gt;        try:&lt;br/&gt;            it = iter(obj)&lt;br/&gt;            return True&lt;br/&gt;        except TypeError:&lt;br/&gt;            return False&lt;br/&gt;&lt;br/&gt;    isit2 = lambda obj: isinstance(obj,basestring) or    \ getattr(obj,'__iter__',False)&lt;br/&gt;&lt;br/&gt;    def isit3(obj):&lt;br/&gt;        return (isinstance(obj,basestring) or getattr(obj,'__iter__',False))&lt;br/&gt;&lt;br/&gt;    #...then:&lt;br/&gt;    '''&lt;br/&gt;    &amp;gt;&amp;gt;&amp;gt; timing(isit3, 100000, [])&lt;br/&gt;    isit3 0.99&lt;br/&gt;    &amp;gt;&amp;gt;&amp;gt; timing(isit2, 100000, [])&lt;br/&gt;    &lt;lambda&gt; 0.99&lt;br/&gt;&lt;br/&gt;    &amp;gt;&amp;gt;&amp;gt; timing(isit, 100000, [])&lt;br/&gt;    isit 0.53&lt;br/&gt;    '''&lt;br/&gt;&lt;/lambda&gt;&lt;/small&gt;&lt;/blockquote&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;/blockquote&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=625c5288-d5c3-86a5-9ec8-ca9e7337f648' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-5237548726478295929?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/5237548726478295929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/04/timing-is-everything.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/5237548726478295929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/5237548726478295929'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/04/timing-is-everything.html' title='Timing is everything'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-5767158586401635191</id><published>2009-04-21T06:06:00.001-07:00</published><updated>2009-04-21T08:51:52.209-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wxWidgets'/><category scheme='http://www.blogger.com/atom/ns#' term='Tkinter'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='GUI'/><category scheme='http://www.blogger.com/atom/ns#' term='wxPython'/><title type='text'>Choosing a Python GUI api</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I narrowed the choice to Tkinter and wxPython fairly quickly--based on Tkinter being the de facto alternative and wxPython being the most discussed alternative on a basic Google search of "Python GUI".&lt;br/&gt;&lt;br/&gt;Also wxPython has the largest widget collection, including a spreadsheet and since what I'm doing will involve a spreadsheet-like interface I decided that further investigation had quickly diminishing returns.&lt;br/&gt;&lt;br/&gt;&lt;a href='http://wiki.python.org/moin/PyQt' target='_blank'&gt;PyQt&lt;/a&gt; looks very powerful, and drives the incredibly impressive &lt;a href='http://www.ailab.si/Orange/' target='_blank'&gt;Orange&lt;/a&gt; application--but failed the "can I install and use it without much brain damage?" test, as did &lt;a target='_blank' href='http://www.gtk.org/'&gt;pyGTK  &lt;/a&gt;(also known as the "can an idiot install it?" test--me being the idiot--if something requires more than one or steps to install, it generally fails this test).   I would not be surprised to need revisit pyQt and pyGTK for larger scale projects.&lt;br/&gt;&lt;br/&gt;The following, very helpful discussion walks through a very simple app in Tkinter and wxPython side-by-side.  Good for understanding the basic differences of the two packages and for understand the basics of GUI programming.&lt;br/&gt;&lt;br/&gt;&lt;a href='http://sebsauvage.net/python/gui/'&gt;Building a basic GUI application in Python with Tkinter and wxWidgets&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;NB:  One fact that might help clear confusion as you surf GUI related posts-- wxWidgets == wxWindows.   The name of the underlying C++ library was changed to wxWidgets at some point (no doubt copyright/trademark related).&lt;br/&gt;&lt;br/&gt;I'm also starting to look at wxGlade, a GUI builder wrapper for wxPython.&lt;br/&gt;&lt;br/&gt;NB, re Editors:  I am using Eclipse with Pydev, with good results.  &lt;br/&gt;&lt;blockquote/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=59c950cf-abc4-8773-9081-533d1fa3c3c0' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-5767158586401635191?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/5767158586401635191/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/04/choosing-python-gui-api.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/5767158586401635191'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/5767158586401635191'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/04/choosing-python-gui-api.html' title='Choosing a Python GUI api'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-1563454546570817398</id><published>2009-04-17T19:09:00.001-07:00</published><updated>2009-04-17T19:09:52.789-07:00</updated><title type='text'>Autumn ORM</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I've been playing with &lt;a href='http://autumn-orm.org/' target='_blank'&gt;Autumn&lt;/a&gt;, a Object Relational Mapper by Jared Kuolt.  First, I can recommend it, highly.  It took me less time to get it up and running and start doing useful things with it than to get through the first sections of the documentation for any of the other ORMs for Python out there. &lt;br/&gt;&lt;br/&gt;Second, an interesting thought reading some of the comments on old posts when Jared first announced Autumn.   Several comments saw no reason to release a new package, feeling more or less strongly, that the open source way is to jump on to one of the existing projects.   This to me is very wrong-headed.&lt;br/&gt;&lt;br/&gt;Part of the power of open source is from the willingness to throw out something because you don't have a tremendous revenue or sunk cost number associated with -- and to start over again using what you learned from the first effort.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=c1ab7fe1-7137-87c0-b04e-5ecd72b5fcf1' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-1563454546570817398?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/1563454546570817398/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/04/autumn-orm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/1563454546570817398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/1563454546570817398'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/04/autumn-orm.html' title='Autumn ORM'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7085952916595348171.post-6225948134021551012</id><published>2009-04-17T18:13:00.001-07:00</published><updated>2009-04-17T18:13:52.098-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python:  Static Methods versus Class Methods</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;The best discussion I've seen regarding the differences between static methods and class methods in Python is an &lt;a href='http://nmiyasato.blogspot.com/2008/06/python-static-vs-class-methods.html' target='_blank'&gt;old post at Miya's blog&lt;/a&gt;.    I like the way Miya approaches it.  Rather than going into the technical discussion found in the Python docs, he asks why would one use static methods, if it seems that class methods can do everything static methods can but not vice versa.&lt;br/&gt;&lt;br/&gt;The key to understanding the difference between the two is in the comments.  A commentor points out&lt;br/&gt;&lt;blockquote&gt;"classmethod give[s] you access to the class's attributes. static method does not so..."&lt;br/&gt;&lt;/blockquote&gt;&lt;br/&gt;Modifying the commentors example slightly:&lt;br/&gt;&lt;blockquote&gt;&lt;big&gt;&lt;font face='monospace'&gt;&lt;small&gt;&lt;small&gt;&amp;gt;&amp;gt;&amp;gt; class MyClass(object):&lt;br/&gt;&lt;br/&gt;        myattribute = 'spam'&lt;br/&gt;&lt;br/&gt;        @classmethod&lt;br/&gt;        def eggs(cls):&lt;br/&gt;            return cls.myattribute&lt;br/&gt;&lt;br/&gt;        @staticmethod&lt;br/&gt;        def static_eggs():&lt;br/&gt;            self.myattribute   &lt;big&gt;&lt;big&gt;&lt;font color='#333333'&gt;# Will this work??&lt;/font&gt;&lt;/big&gt;&lt;/big&gt;&lt;br/&gt;        &lt;br/&gt;&amp;gt;&amp;gt;&amp;gt; MyClass.eggs()             &lt;/small&gt;&lt;/small&gt;&lt;/font&gt;&lt;/big&gt;&lt;big&gt;&lt;font face='monospace'&gt;&lt;small&gt;&lt;small&gt;&lt;big&gt;&lt;big&gt;&lt;font color='#333333'&gt;# O.K. for class method&lt;/font&gt;&lt;/big&gt;&lt;/big&gt;&lt;/small&gt;&lt;/small&gt;&lt;/font&gt;&lt;/big&gt;&lt;br/&gt;&lt;big&gt;&lt;font face='monospace'&gt;&lt;small&gt;&lt;small&gt;'spam'&lt;br/&gt;&amp;gt;&amp;gt;&amp;gt; MyClass.static_eggs()     &lt;/small&gt;&lt;/small&gt;&lt;/font&gt;&lt;/big&gt;&lt;big&gt;&lt;font face='monospace'&gt;&lt;small&gt;&lt;small&gt;&lt;big&gt;&lt;big&gt;&lt;font color='#333333'&gt;# ...not so much for static method&lt;/font&gt;&lt;/big&gt;&lt;/big&gt;&lt;/small&gt;&lt;/small&gt;&lt;/font&gt;&lt;/big&gt;&lt;br/&gt;&lt;big&gt;&lt;font face='monospace'&gt;&lt;small&gt;&lt;small&gt;&lt;font color='#cc0000'&gt;Traceback (most recent call last):&lt;br/&gt;  File "&amp;lt;pyshell#33&amp;gt;", line 1, in &amp;lt;module&amp;gt;&lt;br/&gt;    MyClass.static_eggs()&lt;br/&gt;  File "&amp;lt;pyshell#31&amp;gt;", line 8, in static_eggs&lt;br/&gt;    self.myattribute&lt;br/&gt;NameError: global name 'self' is not defined&lt;/font&gt;&lt;br/&gt;&lt;/small&gt;&lt;/small&gt;&lt;/font&gt;&lt;/big&gt;&lt;/blockquote&gt;To recap:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;Both static and class methods can be called from the class without an instance:&lt;/li&gt;&lt;/ul&gt; &lt;blockquote&gt;&lt;small&gt;&amp;gt;&amp;gt;&amp;gt;MyClass.static_method_that_says_hi()&lt;br/&gt;"HI"&lt;br/&gt;&amp;gt;&amp;gt;&amp;gt;MyClass.class_method_that_says_hi()&lt;br/&gt; "HI"&lt;br/&gt;&amp;gt;&amp;gt;&amp;gt;x = MyClass()&lt;br/&gt;&amp;gt;&amp;gt;&amp;gt;x.static_method_that_says_hi()&lt;br/&gt; "HI"&lt;br/&gt;  &lt;/small&gt;&lt;/blockquote&gt;   &lt;ul&gt;&lt;li&gt;Both can be inherited by sub-classes and maintain their identity (i.e., both are actually static). &lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt; Class methods give you access to a class attributes and static methods do not.&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;So, why use one instead of the other?  Why not just use class methods since they're more powerful?&lt;br/&gt;&lt;br/&gt;For me the principle is to use the simplest structure that handle's problem.   Class methods can do more, and therefore using them should signal that you're class does fairly complicated stuff.  Having a bias to using static methods means that you've thought about parsimony in your design.  &lt;br/&gt;&lt;br/&gt;I'll come up some examples of each and be back.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=54116f63-fc18-86a3-b44b-64a3aaf5cb4d' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7085952916595348171-6225948134021551012?l=bgresearch-bondgeek.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bgresearch-bondgeek.blogspot.com/feeds/6225948134021551012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/04/python-static-methods-versus-class.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/6225948134021551012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7085952916595348171/posts/default/6225948134021551012'/><link rel='alternate' type='text/html' href='http://bgresearch-bondgeek.blogspot.com/2009/04/python-static-methods-versus-class.html' title='Python:  Static Methods versus Class Methods'/><author><name>bondgeek</name><uri>http://www.blogger.com/profile/05272817298826052189</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/_NqF52qh8GN8/Sl8-_1lKvDI/AAAAAAAAAAY/ZvjV8mT0ZV4/S220/bgrsimple.png'/></author><thr:total>0</thr:total></entry></feed>
