Let me show you what I mean. I teach basic algorithms from the book by Sedgewick and Wayne that has a lot of example code in Java. Some of my students are more comfortable with Python than Java, and to help them, I ported some of the book’s code to Python. The following is my version of the book’s code for breadth-first search in a directed graph, written in the constructor closure style. (Scroll down for a “standard” Python class implementation if you’d like to start with that.)
import collections class BFS: def __init__(self, G, s): edge_to = [-1] * G.V(); dist_to = [-1] * G.V(); q = collections.deque() q.append(s) dist_to[s] = 0 while q: # while q not empty v = q.popleft() for w in G.adj(v): if dist_to[w] < 0: # if w not visited q.append(w) edge_to[w] = v dist_to[w] = dist_to[v] + 1 def path(v): if dist_to[v] < 0: return None p = [v] while v != s: v = edge_to[v] p.append(v) p.reverse() return p self.has_path_to = lambda v: dist_to[v] >= 0 self.dist_to = lambda v: dist_to[v] self.path_to = path
Of course, this is not how Python classes are usually written. Translating to what I understand as the standard style gives me this:
import collections class BFS: def __init__(self, G, s): self.__s = s self.__edge_to = [-1] * G.V(); self.__dist_to = [-1] * G.V(); q = collections.deque() q.append(s) self.__dist_to[s] = 0 while q: # while q not empty v = q.popleft() for w in G.adj(v): if self.__dist_to[w] < 0: # if w not visited q.append(w) self.__edge_to[w] = v self.__dist_to[w] = self.__dist_to[v] + 1 def has_path_to(self, v): return self.__dist_to[v] >= 0 def dist_to(self, v): return self.__dist_to[v] def path_to(self, v): if self.__dist_to[v] < 0: return None p = [v] while v != self.__s: v = self.__edge_to[v] p.append(v) p.reverse() return p
The closure version is, in my view, much cleaner than the standard version, riddled with
self parameters and
self.__ prefixes which are easy to forget (it took me several iterations to get them all in place during the translation) and distracting to the reader. Also, the closure version makes the private data truly private, rather than protected by awkward naming conventions.
But maybe I’m overlooking reasons not to use the closure style. Performance factors perhaps? I welcome your opinions.