[Baypiggies] Class methods as constructors?

Alex Martelli aleax at google.com
Wed Sep 3 04:11:00 CEST 2008


Problem with a factory function is that it doesn't generate "the right
subclass"; as a class gets subclassed, the subclasses' authors have to
keep adding corresponding factory functions to make instances of
_them_ instead of ones the original class.

And whenever you see names such as the_factory, subclass1_the_factory,
subclass2_the_factory, that's a very strong code smell: somebody's not
using namespaces and object orientation right.  And "Namespaces are
one honking great idea -- let's do more of those!", as the Zen of
Python says as its rousing conclusion; basically, wanting to use
factory functions instead of factory classmethods rejects this rousing
applause for namespaces, and in a sense all of the Zen of Python.

And yet, it's so *INCREDIBLY* easy...!  Consider:

>>> class mydt(datetime.datetime): " some cool added functionality here "
...
>>> mydt.fromordinal(999999)
mydt(2738, 11, 27, 0, 0)

Could it be any easier?  If the author of the datetime module had been
so silly as to define a factor function datetime_fromordinal (instead
of a class method of the datetime type) the poor author of the mydt
subclass would have had to add their own laboriously named and
boringly implemented mydt_fromordinal factory function -- presumably
using the datetime_fromordinal factory to build a temporary datetime
object, then copying the fields from those.  How much silly
boilerplate and wasted work...!

But luckily, the author of the datetime module didn't make that silly
mistake: they defined a class method, and mydt automatically takes
advantage of it, freely and easily.  Guess that module author
understands and appreciates the Zen of Python, hm?

Considering said author is Tim Peters, who also happened to *write*
the Zen of Python, maybe that's not surprising;-).

As for who's old-fashioned, well, my memory is a bit hazy after so
long, but I believe I recall that Smalltalk '76 didn't yet have class
methods, but Smalltalk '80 introduced them -- and the key use case has
always been "alternate constructors" done RIGHT, as opposed to C++'s
silly alternative of type-based overloading... who's to tell if a
large number passed to a datetime constructor is meant as an ordinal
or as a timestamp?!  Having fromordinal and fromtimestamp as
separately named class methods puts paid to that!

So, averaging the difference, I think I've been using class methods as
alternate constructors starting about 30 years ago (though I had to
forgo them for a sadly long time when using languages that just didn't
HAVE factory methods). How much longer has YOUR
so-called-old-fashioned preferred approach of "factory functions" been
around?-)


Alex

On Tue, Sep 2, 2008 at 5:37 PM, Shannon -jj Behrens <jjinux at gmail.com> wrote:
> On Tue, Sep 2, 2008 at 1:47 PM, Aahz <aahz at pythoncraft.com> wrote:
>> On Tue, Sep 02, 2008, Charles Merriam wrote:
>>>
>>> I have a spot where I need a number of constructors for the same class
>>> and don't want to have too complicated an __init__ function.   Using
>>> class methods seems like the cleanest code.
>>>
>>> x = Spam()   # Simple case
>>> x = Spam.Pickled_Loaf(['Pimentos','Menthos'])
>>> x = Spam.Shake('chunky')
>>>
>>> with code in the Spam class like:
>>>
>>> @classmethod
>>> def Picked_Loaf(additives, extra_gelatin = False):
>>>      assert not ('Menthos' in additives and 'Diet Coke' in additives)
>>>      i = Spam()  # make an instance
>>>      i.additives = additives
>>>      i.add_to_production_queue(Process.chopping)
>>>      return i
>>
>> You probably don't want to use assert -- that gets optimized away with
>> .pyo files.
>>
>> Overall, I personally would be more inclined to use a factory function
>> or a slightly more complicated __init__ that dispatches, but there's
>> nothing wrong with what you're doing.
>
> Call me old school, but I still use factory functions (i.e. outside
> the class) like Aahz, but what you're doing is perfectly fine.
>
> -jj
>
> --
> Don't you wish you had a really clever sig like mine?
> http://jjinux.blogspot.com/
> _______________________________________________
> Baypiggies mailing list
> Baypiggies at python.org
> To change your subscription options or unsubscribe:
> http://mail.python.org/mailman/listinfo/baypiggies
>


More information about the Baypiggies mailing list