Using namedtuples with method and instance variable inheritance

Python’s namedtuple class provides a simple, lightweight way to make simple immutable classes. If you’re using dictionaries to pass objects around, consider using namedtuples instead: they’re easier to read and provide the benefits of classes such as methods and properties. With namedtuples, you’ll have cleaner code with essentially no additional work.

The Python namedtuple docs include examples for Point and Point3D. Point3D inherits the instance variables (“fields” in namedtuples), but not the methods of the Point class. What’s not discussed in the documentation is how to inherit methods and fields when using namedtuples, and that’s the subject of this post.

Let’s start with the examples from the docs. The first example is:

Point = collections.namedtuple('Point', ['x', 'y'])
p = Point(5,6)

This is quite useful in itself because it allows us to access p.x and p.y as properties, which many find to be preferable to p[‘x’] or p[‘y’] with a dict-based structure.

But Points often need to be manipulated, and object-oriented programmers often prefer to put the code for such manipulations with the class than as standalone functions. With namedtuples, that might look like this (again, from the docs):

class Point(namedtuple('Point', 'x y')):
__slots__ = ()
def hypot(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
def __str__(self):
return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)

Great, we now have methods associated with the class.

The docs go on to define Point3D with an additional dimension:

Point3D = namedtuple('Point3D', Point._fields + ('z',))

Although Point3D “inherits” fields from Point, it doesn’t inherit any methods. In fact, Point3D isn’t a subclass of Point at all. In the example above, we merely copied one aspect of the definition of Point to make Point3D. So, if there were methods in Point, they would not be available to Point3D. In the real world, method inheritance is useful for abstraction and code maintenance.

Like all classes, classes derived from namedtuples may be subclassed and their methods overridden. Consider an imaginary number class like this that formats imaginary numbers in typical a + bi notation.

class Point_img(Point):
def __str__(self):
return 'Point: %6.3f+%6.3fi' % (self.x, self.y)

So, it’s now time to combine class inheritance and extending a namedtuple’s fields. Let’s define a new Point2D and Point3D classes like this:

from collections import namedtuple
class Point2D(namedtuple('Point', ['x', 'y'])):
def length(self):
return sum([ d**2 for d in self ]) ** 0.5
def __add__(self,other):
assert self.__class__ == other.__class__, "may only add instances of same class"
return self.__class__.__new__(self.__class__,*[ d1+d2 for d1,d2 in zip(self,other) ])
def __str__(self):
return '%s: <%s>; length=%6.3f' % (
','.join([ '%s=%6.3f' % (d,v)
for d,v in zip(self._fields,self) ]),
class Point3D(namedtuple('Point3D', Point2D._fields + ('z',)), Point2D):

Notice that Point3D is derived from two classes: a namedtuple-based class defined by adding to _fields, and the Point2D class which defined methods (and was itself derived from a namedtuple). This isn’t rocket science, but it’s a obscure and potentially very useful to others.

With these definitions, we may now define 2D and 3D points. Notice that Point3D inherits the addition and string representation methods of Point2D.

In [21]: print Point2D(3,4)
Point2D: <x= 3.000,y= 4.000>; length= 5.000

In [22]: print Point2D(3,4) + Point2D(5,6)
Point2D: <x= 8.000,y=10.000>; length=12.806

In [23]: print Point3D(3,4,5)
Point3D: <x= 3.000,y= 4.000,z= 5.000>; length= 7.071

In [24]: print Point3D(3,4,5) + Point3D(1,2,3)
Point3D: <x= 4.000,y= 6.000,z= 8.000>; length=10.770

Finally, it’s worth noting that designing the notion that Point3D is-a Point2D is dubious. If I were going to implement this, I’d probably start with a generic n-dimensional point that had the methods described above, and then subclass special cases like Point2D and Point3D as needed.

Highlighting the active tab in GNOME terminal

In recent iterations of GNOME terminal, the active tab is nearly indistinguishable from the inactive ones.  That makes it harder to navigate when you’ve got a bunch of terminals open simultaneously. Fortunately, GNOME uses a modified CSS scheme to control theme appearance, and that makes it easy to highlight an active tab. Here’s how.

Create (or edit) ~/.config/gtk-3.0/gtk.css. Add these lines:

@define-color ubuntu_orange #fb9267;
TerminalWindow .notebook tab:active {
 background-color: shade(@ubuntu_orange,1.1);

Then, exit all open terminals, and then open a new terminal and create a tab. With the above modification, you should see tabs like this:

GNOME terminal tabs

Using virtualenv, pip, and ipython

This page provides a quick synopsis on how to use three of my favorite Python features together:

  • virtualenv, which provides a standardized mechanism to isolate python environments (including in WSGI setups)
  • pip, which facilitates packages installation in virtualenv environments or otherwise
  • ipython, a terrific interactive shell with readline and debugging support

Continue reading “Using virtualenv, pip, and ipython”

Bolloxed sharing in Google docs

Google’s implementation of document sharing is completely fouled up. The following is a slighted redacted version of a (formerly) internal email to colleagues to tell them what I learned about document sharing based on interactions with their customer support and folks on the net.

Continue reading “Bolloxed sharing in Google docs”

Where is our (Hello) World going?!

Hype and evangelism run rampant in technology. That’s not to say there aren’t real and substantial advances, of course. One of my personal mantras is that simple things should be simple and complex should be possible. In other words, complexity shouldn’t come at the expense simplicity. (This isn’t a novel idea, just my own internal rephrasing.) With that in mind, I was amused by the following observation:

Continue reading “Where is our (Hello) World going?!”

Monitor your router with (r)syslogd

I’m having lots of dropped connections at home. Unfortunately, consumer-grade routers typically have poor monitoring facilities out of the box. Unix/Linux environments have long been able to aggregate logging messages across multiple hosts through a service called syslog. Many routers use embedded Linux and support sending messages to remote systems via syslog. (Emailing logs is supported, but that’s a clumsy option.) This post is a short tip on how to configure a D-Link DI-825 (rev B1) to send system messages to an Ubuntu 10.0 host, but the general method will apply to many routers and nearly all Unix/Linux hosts are capable of acting as logging destinations. Continue reading “Monitor your router with (r)syslogd”

A Roundup of Investigations into Direct-to-Consumer Genetic Testing

Earlier this week, the Oversight and Investigation subcommittee of the Energy and Commerce committee of the US House of Representatives undertook an investigation of direct-to-consumer (DTC) testing. To some, this investigation was long overdue; to others, it was a witch hunt by intrusive regulators. In any case, it’s pretty clear that this event will lead to regulatory oversight that will permanently shape genetic testing. Below, I’ve provided a few links with comments and highlights. Continue reading “A Roundup of Investigations into Direct-to-Consumer Genetic Testing”

Relocating a primary site directory

My hosting provider, HostMonster, uses cPanel to enable account administrators to configure their domains and services. By default, Hostmonster and cPanel place web data for the primary domain in ~/public_html/, with subdomains and “add-on” domains as subdirectories therein. That means that files for the primary domain are comingled with the document roots of other domains. The incongruency of that layout causes heartburn for people like me. This post tells you how to relocate those files AND have them served by the original URLs for the primary domain. Continue reading “Relocating a primary site directory”

Have Monkeys, Need Climbing Wall

blue-holdI have three kids. All of them like to climb. Margot seems unnaturally compelled to climb things — no matter how imprudent. (She broke her clavicle at age 2 after climbing up to, and falling off of, the kitchen table.) Unfortunately, our San Francisco postage stamp yard has no good places to climb. Since I spent most of my childhood in a tree, the lack of climbable structures for my kids disturbed me. So, during a recent break between jobs, I built a climbing wall in our house. The kids love it and it was a hit at our recent holiday cookie party.

Continue reading “Have Monkeys, Need Climbing Wall”

I Joined Berkeley

Stanley Hall

As many of you know by now, I left Genentech in September to join UC Berkeley as the Chief Scientist of the Genome Commons. I’m part of QB3, the California Institute for Quantitative Biology (no I don’t understand the abbreviation either).

I’m collaborating with Steven Brenner, Jasper Rine, and Lior Pachter at Berkeley, and Robert Nussbaum and Bernie Lo at UCSF, to address the technical, scientific, clinical, and ethical opportunities associated with interpreting genomic data. It’s an exciting time and an exciting place.

To be sure, I’ll be posting a lot more about that here.