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.