Sometimes your class design warrants the definition of multiple construction methods for a class, such as rebuilding from a serialized form vs. normal internal construction with explicit parameters. This recipe gives an example of using class level methods to create such constructors.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
# example class with ordinary constructor and class-level factory method class Color: """class for specifying colors while drawing BitMap elements""" def __init__( self, r=0, g=0, b=0 ): self.red = r self.grn = g self.blu = b def __str__( self ): return "R:%d G:%d B:%d" % (self.red, self.grn, self.blu ) def toLong( self ): return ( long(self.blu) ) + \ ( long(self.grn) << 8 ) + \ ( long(self.red) << 16 ) def fromLong( cls, lng ): blu = lng & 0xff lng = lng >> 8 grn = lng & 0xff lng = lng >> 8 red = lng & 0xff return cls( red, grn, blu ) fromLong = classmethod( fromLong ) c = Color( 255, 0, 0 ) # red print c colorInt = c.toLong() print colorInt print Color.fromLong( colorInt )
This is sort of a C++-ish technique (but I've seen it in Smalltalk too), and it requires using a small wrapper class to convert the defined instance function into a class function, but I think it works well.
This is a simple example of a Color class with an ordinary initializer taking 3 integers, each for red, green, and blue, and then a class level factory method named fromLong that takes a single long integer (such as might be found in a bitmap palette).
Why not use static method for fromLong. I don't understand the utility of you wrapper class...
Legacy workarounds never die, they just keep cropping up in new code... I borrowed this wrapper class from another recipe, out of ignorance of "recent" Python features. "classmethod" would work just fine, I just didn't know it existed.
So corrected... (and I removed the extraneous commentary for the now unnecessary class)
Ooops, still wrong... Not "classmethod" I meant "staticmethod". No reason to involve the class.
Why not classmethod? I think it's even better with classmethod. Your initializer then does not break when you rename the class.
To mike mazurek: This is not a wrapper class, it is just a small excerpt of a larger class, illustrating two different construction interfaces. And just defining a global method "fromLong" doesn't help the user of this class very much - scoping as a staticmethod or classmethod within the Color class helps maintain the connection between this method and the class for which it acts as a factory method. The user's code calling a global method:
is more self-explanatory when included with the Color class:
To Goerg Brandl: Point taken, changed back to a classmethod.