Class design issues: multiple constructors

Greg Brunet gregbrunet at NOSPAMsempersoft.com
Thu Aug 7 12:20:09 EDT 2003


Hi Alex

"Alex Martelli" <aleax at aleax.it> wrote in message
news:SiqYa.27810$an6.980707 at news1.tin.it...

> >  I'm also
> > thinking that I might rather name the methods more specifically
(such as
> > Open & Create) instead of both being __init__.  What would be the
>
> Right.  The Pythonic way is to provide "factory functions" that
prepare
> and return the object you need.  Cosmetically, you may make the
factory
> functions part of the class itself, using the staticmethod and
classmethod
> built-in types of Python 2.2 and later -- no real need, but some
people
> are very keen on this style, so Python now supports it.

It sounds like option #1 in Miki's response to my post would be called
factory functions.  I can see how that would work - pretty
straightforward & understandable.


> > Pythonic way to go about doing this?  Would I make an __init__,
Open, &
> > Create methods, and make 2 calls for each DBF object, like this:
> >
> > class dbf:
> >     __init__(self):
> >         pass
> >     Create(self, filename, fieldDefs):
> >         pass
> >     Open(self, filename):
> >         pass
>
> No, it should rather be something like:
>
> class dbf(object):
>     # no need to define __init__ if it's empty!
>     def Create(filename, fieldDefs):
>         result = dbf()
>         # use filename and fieldDefs to populate 'result'
appropriately
>         return result
>     Create = staticmethod(Create)
>     def Open(filename):
>         result = dbf()
>         # use filename to populate 'result' appropriately
>         return result
>     Open = staticmethod(Open)

A couple of things.  First, I was mostly trying to indicate the
structure of the class.  I'm thinking that there might in fact be some
__init__ code present that would be shared by both the Open & Create
functions.  In that case, I would expect that the corresponding
"result=dbf()" code in the functions would invoke the __init__ code -
correct?

I'm also confused by the omission of "self" from the function/method
definitions.  It seems that these functions are 'Class-level' methods
(which would explain the term staticmethod I expect <g>).  So at the
time they are invoked, an instance/object has not been created (and thus
we are returning it: result).


> > # open existing file
> > f1 = dbf()
> > f1 = dbf.Open('customer.dbf')
>
> No, this wouldn't work with the code you propose; it would with
> the variant I suggest, but the first of these statements is useless
> so you should remove it.

Agreed - I was looking for a way to get rid of the initial "f1=dbf()"
statement, and your technique embeds that in the Open call - which is
great.  The same applies to the Create function call.

However, something that's got me more confused is that after getting
your response, I read the "Unifying types and classes in Python 2.2"
section of the docs, specifically the "Static methods and class methods"
section.  They give an example of:

    class C:
        def foo(x, y):
            print "staticmethod", x, y
        foo = staticmethod(foo)

    C.foo(1, 2)
    c = C()
    c.foo(1, 2)

What concerns me here is what would happen if someone did indeed perform
the "f1=dbf()" before the "dbf.Open" call?  The sample from the manual
shows that kind of usage.  In my situation, it seems that I would be
creating an (empty) dbf object, then throwing it away and replacing it
with the result of the Create or Open statement.  Is there some way to
prevent someone from using "f1=dbf()", since doing so would leave them
with an unusable object?

Thanks for your excellent help!

-- 
Greg





More information about the Python-list mailing list