Recently in Python Category

Python Variable Naming Gotcha

| No Comments | No TrackBacks
Last fall, I had an interview that turned out to be challenging. While I did quite well on most of it, there was one question I simply could not answer. The question was this -- given the following code, what can you see as being a possible issue:
def append_list(x=[]):
    x.append(1)
    return x
I -- like many other people -- couldn't see anything wrong with this. I simply assumed the default parameter would be used in lieu of calling with an actual value. However, examine the following snippet. func1 is the aforementioned function. func2 is the proper definition:
#!/usr/bin/env python

def func1(x=[]):
    x.append(1)
    return 'x = %15s, id(x) = %s' % (x, id(x))

def func2(x=None):
    if x is None:
        x = []
    x.append(1)
    return 'x = %15s, id(x) = %s' % (x, id(x))

for f in (func1, func2):
    print '%s %s' % (f.__name__, f())
    print f.__name__, f()
    print f.__name__, f()
    print f.__name__, f([2])
    print f.__name__, f()
    print
The above snippet will produce something like the following. Have a close look:
$ ./gotcha.py 
func1 x =             [1], id(x) = 3084437356
func1 x =          [1, 1], id(x) = 3084437356
func1 x =       [1, 1, 1], id(x) = 3084437356
func1 x =          [2, 1], id(x) = 3084466828
func1 x =    [1, 1, 1, 1], id(x) = 3084437356

func2 x =             [1], id(x) = 3084466828
func2 x =             [1], id(x) = 3084466828
func2 x =             [1], id(x) = 3084466828
func2 x =          [2, 1], id(x) = 3084466828
func2 x =             [1], id(x) = 3084466828
As you can see, func1's output is completely unexpected (well maybe not depending on who you are). The problem here has nothing to do with variable scope as I originally assumed. It's actually because I didn't understand Python variables and how they have some fundamental differences to other language implementations. This page has some very good explanations for several Python idioms. In fact, that link pretty much explains this behavior.

Fun With Mac and 'say'

| No Comments | No TrackBacks
This is officially what happens when a geek gets bored. A friend of mine was over tonight, and he showed me the 'say' utility on Mac OSX. Well, you can imagine where this went. Say no more:

#/usr/bin/env python

from htmlentitydefs import name2codepoint as n2cp
import re
import urllib2
import os
import time
import string

class HTMLDecode(object):
    '''http://snippets.dzone.com/posts/show/4569
       There is absolutely no reason for this to be in a class. I just put it in one.
    '''
    __slots__ = ['substitute_entity','dcdhtmlent']
    def substitute_entity(self, match):
        ent = match.group(3)
        if match.group(1) == "#":
            if match.group(2) == '':
                return unichr(int(ent))
            elif match.group(2) == 'x':
                return unichr(int('0x'+ent, 16))
        else:
            cp = n2cp.get(ent)
            if cp:
                return unichr(cp)
            else:
                return match.group()

    def dcdhtmlent(self, string):
        entity_re = re.compile(r'&(#?)(x?)(\w+);')
        return entity_re.subn(self.substitute_entity, string)[0]

class SpeakFarkHeadlines(object):
    '''This is what happens when you are bored and/or easily amused.'''
    __slots__ = ['headlines','speak']
    def __init__(self):
        self.headlines = []
        dcdr = HTMLDecode()
        response = urllib2.urlopen('http://www.fark.com')
        headline_re = re.compile(r'<span\sclass="headline">(.*?)</span>')
        while True:
            try:
                search = re.search(headline_re, dcdr.dcdhtmlent(response.next().encode('UTF-8')))
                if search:
                    self.headlines.append(search.group(1))
            except StopIteration:
                break

    def speak(self):
        for entry in self.headlines:
            print entry         # Below is nasty hack for shell string scanning and quotes
            os.popen('say \'%s\'' % string.replace(entry, '\'', ''))
            time.sleep(5)

app = SpeakFarkHeadlines()
app.speak()

Now just sit back and have a good chuckle.

About this Archive

This page is an archive of recent entries in the Python category.

Linux is the previous category.

Random is the next category.

Find recent content on the main index or look in the archives to find all content.

Pages