My Stuff
Email
Twitter
Front Page
Presentations
Projects
Music
Favorite Quotes

Respect
Vincent Foley-Bourgon
Sam Griffith
LeRoy Mattingly
Colin Putney
Matt Secoske
Sam Tesla
Andres Valloud

Admiration
Leo Brodie
Avi Bryant
Alan Cooper
Steve Dekorte
Stephane Ducasse
Doug Engelbart
Eric Evans
Brian Foote
Martin Fowler
Paul Graham
Dan Ingalls
Alan Kay
John McCarthy
Steve McConnell
Peter Norvig
Niall Ross
Randall Smith
Gerald Jay Sussman
David Ungar
Rebecca Wirfs-Brock
...And So Many More...

My Amps
Squeak
JavaScript
Scheme
Java
Corman Lisp
Ruby
Dolphin Smalltalk
Cincom Smalltalk
Self

Archives
05/01/2003 - 06/01/2003
06/01/2003 - 07/01/2003
07/01/2003 - 08/01/2003
08/01/2003 - 09/01/2003
09/01/2003 - 10/01/2003
10/01/2003 - 11/01/2003
11/01/2003 - 12/01/2003
12/01/2003 - 01/01/2004
01/01/2004 - 02/01/2004
02/01/2004 - 03/01/2004
03/01/2004 - 04/01/2004
04/01/2004 - 05/01/2004
05/01/2004 - 06/01/2004
06/01/2004 - 07/01/2004
07/01/2004 - 08/01/2004
08/01/2004 - 09/01/2004
09/01/2004 - 10/01/2004
10/01/2004 - 11/01/2004
11/01/2004 - 12/01/2004
12/01/2004 - 01/01/2005
01/01/2005 - 02/01/2005
02/01/2005 - 03/01/2005
03/01/2005 - 04/01/2005
04/01/2005 - 05/01/2005
05/01/2005 - 06/01/2005
06/01/2005 - 07/01/2005
07/01/2005 - 08/01/2005
08/01/2005 - 09/01/2005
09/01/2005 - 10/01/2005
10/01/2005 - 11/01/2005
11/01/2005 - 12/01/2005
12/01/2005 - 01/01/2006
01/01/2006 - 02/01/2006
02/01/2006 - 03/01/2006
03/01/2006 - 04/01/2006
04/01/2006 - 05/01/2006
05/01/2006 - 06/01/2006
06/01/2006 - 07/01/2006
07/01/2006 - 08/01/2006
08/01/2006 - 09/01/2006
09/01/2006 - 10/01/2006
10/01/2006 - 11/01/2006
11/01/2006 - 12/01/2006
12/01/2006 - 01/01/2007
01/01/2007 - 02/01/2007
02/01/2007 - 03/01/2007
03/01/2007 - 04/01/2007
04/01/2007 - 05/01/2007
05/01/2007 - 06/01/2007
06/01/2007 - 07/01/2007
07/01/2007 - 08/01/2007
08/01/2007 - 09/01/2007
09/01/2007 - 10/01/2007
10/01/2007 - 11/01/2007
11/01/2007 - 12/01/2007
12/01/2007 - 01/01/2008
01/01/2008 - 02/01/2008
02/01/2008 - 03/01/2008
03/01/2008 - 04/01/2008
04/01/2008 - 05/01/2008
05/01/2008 - 06/01/2008
06/01/2008 - 07/01/2008
07/01/2008 - 08/01/2008
08/01/2008 - 09/01/2008
10/01/2008 - 11/01/2008
01/01/2009 - 02/01/2009
09/01/2009 - 10/01/2009
10/01/2009 - 11/01/2009

Feed

Add this feed to a running copy of BottomFeeder

Monday, October 05, 2009

method_missing in Python

 
OK, I know there is a few implementations of this knocking around on the net already, but I'm in learning mode. So, here's my implementation of Ruby's method_missing:
class PossibleMissingAttribute(object):
def __init__(self, object, name):
self._object = object
self._name = name

def __call__(self, *args, **kwargs):
return self._object._method_missing(self._name, *args, **kwargs)

def __str__(self):
return self.__class__.__name__ + ": " + str(self._object) + "." + self._name

def __getattr__(self, name):
return None

def __nonzero__(self):
return False

class MethodMissingError(Exception):
def __init__(self, object, name, *args, **kwargs):
self.object = object
self.name = name
self.args = args
self.kwargs = kwargs

def __str__(self):
return repr(str(self.object) + "." + self.name)

class Missing(object):
def __getattr__(self, name):
return PossibleMissingAttribute(self, name)
def _method_missing(self, name, *args, **kwargs):
raise MethodMissingError(self, name, *args, **kwargs)


Three objects and that's it! One to be a placeholder when an argument is missing. One object to represent the MethodMissingError and the last to be an abstract class to inherit from. But, you could easily just put these methods anywhere. Here's my tests:
import unittest

class TestMissing(unittest.TestCase):
def test_missing(self):
class TestClass(Missing):
def __str__(self):
return self.__class__.__name__
def existing(self):
return "i am"
def _method_missing(self, name, *args, **kwargs):
return args[0]
self.assertEquals("am not", TestClass().missing("am not"))
self.assertEquals("i am", TestClass().existing())
self.assertEquals(None, TestClass().missing.something_else_missing)
self.assertFalse(TestClass().missing)
self.assertEquals("PossibleMissingAttribute: TestClass.missing", str(TestClass().missing))

def test_exception(self):
class TestClass(Missing):
def __str__(self):
return self.__class__.__name__
self.failUnlessRaises(MethodMissingError, lambda: TestClass().missing())



You've seen my implementation. Here's another one that I found on the net: method_missing in Python
class MethodMissing(object):
def method_missing(self, attr, *args, **kwargs):
“”" Stub: override this function “”"
raise AttributeError(”Missing method %s called.”%attr)

def __getattr__(self, attr):
def callable(*args, **kwargs):
return self.method_missing(attr, *args, **kwargs)
return callable

Um, this version is much shorter than mine. It gets the same job done and is more obvious of what it is doing. Simply returning a function on __getattr__ is the best way to go. It's what my PossibleArgumentMissing was doing. But, where I tried to get all fancy using __call__ to mimic a function which caused my version to be longer. I was also trying to get the argument to come back to return false in if conditions and be almost like None (again, I'm learning and was looking at what was possible). Simplest is best.

This was a fun thought exercise. I love all the hooks Python provides to allow you to get underneath the hood if need be. I will be soon doing a post on descriptors and even decorators. I find Python tends to sway heavier on the functional side of programming versus object-oriented. I'm loving the succinct, yet readable code. Too many languages get into the being so terse that they sacrifice readability or debugability (is that a word? Is now!).

Labels: ,


Comments



Web hosting by ICDSoft

Metalheads Against Racism
This page is powered by Blogger. Isn't yours?


My Weekly Top 20 Artists