Bimorphic methods in Python
Posted by kernelbob on June 15, 2008
Methods in Python are either instance methods (the default), static, or class methods. You can create the latter two using the @staticmethod and @classmethod decorators.
But maybe it would be better to have a single function that can be called either as a class method or an instance method. I coined the term bimorphic method for this, and I wrote a decorator that can make a method bimorphic.
Here’s an example with a bimorphic method.
class MyClass: @bimorphicmethod def my_method(cls, self, arg): if self: print "I'm an instance method of object %s" % self else: print "I'm a class method of class %s" % cls.__name__
When my_method is called as an instance method, self is the instance. Otherwise, self is None and it’s a class method.
And here’s the implementation. It’s pretty simple if you’re familiar with Python’s descriptor protocol. (I wasn’t, so I had to look it up.)
class bimorphicmethod(object): def __init__(self, func): self.func = func def __get__(self, obj, type=None): return lambda *args, **kwargs: self.func(type, obj, *args, **kwargs)
Not convinced? Okay, here’s the “real world” use case.
I’m writing a parser. The parser uses tokens. There are several types of token, such as Identifier. There are also some overloaded token types, such as Keyword. Keyword is a single class that matches all the keywords in the language.
Back to the parser. The parser is driven by data representing its grammar productions. The right side of a grammar production can contain token classes such as Identifier, which matches any identifier, and it can also contain token instances, such as Keyword(‘while’), which matches that specific keyword.
The parser parses a production by passing the parse() message to every symbol in the production. So Token needs to implement a class method called parse() and also an instance method called parse().
There are other solutions. For example, each keyword could be a distinct class. That’s a lot of typing, though. It would introduce about 40 additional classes for this particular language. So bimorphicmethod was born.