Transcript of Radiolab’s “Words” episode for the hearing impaired.

When I heard the Radiolab episode “Words” on their podcast, one of the first things that came to mind was sharing the story of the deaf children in Nicaragua with a deaf friend of mine.  I spent a few minutes trying to find a transcript on their website, and as far as I could tell, there was none. I sent them a quick e-mail a few weeks ago, and today they responded, with a link to a full transcript of the show!

Huge thanks to Tim at Radiolab!

Posted in General | Leave a comment

Python datetime quiz

Without looking at the documentation (or running the code), describe the outputs of the following 4 function calls:

from datetime import datetime

datetime.datetime.now()
datetime.datetime.today()
datetime.datetime.now().date()
datetime.datetime.today().date()

Post your answers as a comment.

Posted in General | Tagged , | 2 Comments

Pitfalls of Python’s ‘is’ operator

I saw this post on Friendfeed, and thought I’d reproduce the code here, because it’s a really interesting Python snippet, and to me, basically says never, ever use the ‘is’ operator.  Here’s the snippet that I just reproduced on Python 2.5.2 and 2.6.5:

In [1]: a = 500

In [2]: b = 500

In [3]: a == b
Out[3]: True

In [4]: a is b
Out[4]: False

In [5]: p = 50 

In [6]: q = 50

In [7]: p is q
Out[7]: True

Totally crazy, right?

The ‘is’ operator is testing “are these objects completely identical” In other words, are they pointing at the same implementation. For basic types like integer, things get complicated, because Python treats integer values between -5 and 256 differently. There’s some hint at this when looking at the documentation for the function PyInt_FromLong(), which takes a C++ long and returns the Python integer representation of that object. The comment there says:

The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object.

And thus, values outside of that range have different implementations, and thus, return False when comparing via ‘is’.  There’s also some discussion of this on StackOverflow.

Posted in General | Tagged , , , , | 1 Comment

5 Things you think upgrading your computer software is going to do.

When you upgrade your computer’s OS or some big program, you’re always doing it for a reason.  Here they are:

  1. Upgrading is going to support the drivers for that new device you just got. (Sorry, it won’t.)
  2. Upgrading is going to make your computer faster. (Really?)
  3. Upgrading is going to make your computer crash less. (Actually, more.)
  4. Upgrading is going to make that one program not hoze your whole system anymore. (That program has been removed from the distribution.)
  5. Upgrading is going to give you lots of great, new features. (You really think things have changed that much?)
Posted in General | Leave a comment

Using Django’s widthratio template tag for multiplication & division.

I find it a bit odd that Django has a template filter for adding values, but none for multiplication and division. It’s fairly straightforward to add your own math tags or filters, but why bother if you can use the built-in one for what you need?

Take a closer look at the widthratio template tag. Given {% widthratio a b c %} it computes (a/b)*c

So, if you want to do multiplication, all you have to do is pass b=1, and the result will be a*c.

Of course, you can do division by passing c=1. (a=1 would also work, but has possible rounding side effects)

Note: The results are rounded to an integer before returning, so this may have marginal utility for many cases.

So, in summary:

to compute A*B: {% widthratio A 1 B %}
to compute A/B: {% widthratio A B 1 %}

And, since add is a filter and not a tag, you can always to crazy stuff like:

compute A^2: {% widthratio A 1 A %}
compute (A+B)^2: {% widthratio A|add:B 1 A|add:B %}
compute (A+B) * (C+D): {% widthratio A|add:B 1 C|add:D %}

Posted in General | 2 Comments

How to tell when your method is on the wrong class.

1. Your code uses self on the RHS of an assignment.

Here’s a Python example:

class accumulator(object):
  def __init__(self):
    self.sum = 0 

class value(object):
  def __init__(self):
    self.value = 0 

  def accumulate(self, accum_instance):
     accum_instance.sum += self.value

Instead of saying:

a = accumulator()
v = value()
v.accumulate(a)

These methods should be re-arranged such that we don’t have “self.value” on the RHS of the assignment in the accumulate method, which would make our calling code look like this:

a = accumulator()
v = value()
a.accumulate(v)

The calling actually looks quite similar, but the semantics of who’s responsible for the work is more clear.

2. You have method names like “add_to”, “increment_by”, “combine_with” or “compute_from”

Instead of calling “self.increment_by(bar)” you should likely be calling “bar.increment(self)”

Note, this violates one of my rules below of passing only “self” as a method argument. At some point, the difference between foo.method(self) and self.method(foo) becomes subjective, and it’s your job as the programmer to decide how these pieces of code relate to each other, and where the functional separation lies. The best way to decide issues like this is to try to come up with some rule for where methods live and behave. The exact guts of “method” would need to be known — is it modifying self, or it’s argument, or both? Try to come up with a rule like “treat arguments as const wherever possible” and you may find that these issues sort themselves out. You may even find that splitting a class up, or joining two classes together might be a good solution to make your code more readable.

3. Your method doesn’t use “self” at all, or only very minimally.

Here’s another surprisingly common practice, a method that looks like this:

def some_method(self, foo, bar, baz):
  self.counter += 1
  foo.process(bar)
  bar.aggregate()
  baz.compute_from(bar)

This method should likely live somewhere outside of the current class, and in the classes
of foo, bar, or baz.

4. You’re passing self (and no other arguments) as an argument to another method.

If you have code that says:

some_class.some_method(self)

Then you likely want to say:

self.better_method(some_class)

Similarly, passing a handful of member variables from self to another method is an indication that method should live in the current class.  For example:

some_class.some_method(self.foo, self.bar, self.baz)

could be rewritten as:

self.better_method(some_class)

Unless better_method would end up violating more of these rules. :)

5. Your method delegates most of it’s functionality to another class or module.

For example:

def some_method(totally_reasonable_argument):
  other_class.process(totally_reasonable_argument)
  other_class.member_variable += self.size
  other_class.log(totally_reasonable_argument)

Look how every line calls into functions in other_class (which could also be a module). Clearly, this method should be living inside other_class and not on the current class.

6. Your method returns an instance of a different class.

For example:

class SomeClass(object):
  def generate_something(foo, bar):
    # likely some computation involving foo & bar here...
    # but, we're returning an instance of a totally different class.
    # This method should likely be split into 2 pieces, one living here,
    # and another piece in class something.
    return something(foo, bar)

Of course, there’s always a time and a place for a factory method, but in Python, these should actually be fairly few and far between.

Posted in General | Leave a comment

Best error message I’ve seen in a long time.

This came from a Gnome-enabled program on by Ubuntu 10.04 system.  It pretty much sums up what’s wrong with “Linux on the desktop”

Error setting value: No database available to save your configuration: Unable to store a value at key ‘/desktop/gnome/url-handlers/unknown/command’, as the configuration server has no writable databases. There are some common causes of this problem: 1) your configuration path file /etc/gconf/2/path doesn’t contain any databases or wasn’t found 2) somehow we mistakenly created two gconfd processes 3) your operating system is misconfigured so NFS file locking doesn’t work in your home directory or 4) your NFS client machine crashed and didn’t properly notify the server on reboot that file locks should be dropped. If you have two gconfd processes (or had two at the time the second was launched), logging out, killing all copies of gconfd, and logging back in may help. If you have stale locks, remove ~/.gconf*/*lock. Perhaps the problem is that you attempted to use GConf from two machines at once, and ORBit still has its default configuration that prevents remote CORBA connections – put “ORBIIOPIPv4=1″ in /etc/orbitrc. As always, check the user.* syslog for details on problems gconfd encountered. There can only be one gconfd per home directory, and it must own a lockfile in ~/.gconfd and also lockfiles in individual storage locations such as ~/.gconf

Posted in General | 1 Comment

Hey Flipboard! Those are my kids!

So, the press is somewhat buzzing about the new Flipboard iPad app, as well as their acquisition of Ellerdale.  Here’s a screenshot of the second page of their slideshow:

(click to zoom).  The large image of the kid with the blue hat is my daughter Maya, and my son is standing behind her (wearing a green shirt and orange hat).  We took that photo when we were goofing off at the Palo Alto JJC a couple of weeks ago!  Here’s the original source photo that I downloaded from my wife’s FB account:

Awesome!

Posted in General | 3 Comments

Alternative to GoDaddy DNS hosting?

I’ve heard that GoDaddy is a pretty crappy DNS service. Generally, people seem to complain that their origin DNS servers are quite slow.

I have observed that every once in a while, I do get quite slow DNS resolution of my GoDaddy hosted domains, and would switch if there was an easy (and free) alternative.

I’m surprised that OpenDNS and Google Public DNS don’t let people add their own DNS records for their domains.  This seems to me like a natural extension to the services they’re providing.

I’d love to hear if you have any alternatives to GoDaddy that are “known better” in their response times, and that are reputable and reliable.   Self-hosting DNS has always seemed like a bad idea to me, but it could be an alternative if the arguments for it are strong enough.

Posted in General | Tagged , , | 2 Comments

More Python style discussions.

So, I work with a lot of code that likes to do stuff like this:

def process(some_dict, some_key):
  sum = 0
  value = some_dict.get(some_key, None)
  if value is not None:
    sum += value
  return sum

but I find the use of get() to be really gratuitous (especially in this case) and would rather write:

def process(some_dict, some_key):
  sum = 0
  if some_key not in some_dict:
    return sum
  sum += some_dict[some_key]
  return sum

But I’m sympathetic to the original author’s form, because in my form, I’m querying the dict twice, whereas in theirs, they’re doing it once. I guess another alternative would be:

def process(some_dict, some_key):
  sum = 0
  try:
    sum += some_dict[some_key]
  except KeyError:
    pass
  return sum

I’d love to hear your thoughts on which of these is the most Pythonic (or maintainable, or readable) form for this kind of logic.

Note that these examples are purely synthetic, and there’s usually an extra set of looping to calculate the sum. I’ve just simplified things to make it look nice.

Posted in General | 1 Comment