473,387 Members | 1,779 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Class design issues: multiple constructors

I'm trying to write a package to handle working with DBase files.
There's enough different stuff in handling them (unfortunately) that I'm
not going to try to the interface DB-API 2.0 compliant - it'll be a
lower level wrapper around reading & writing the DBF files. In trying
to design a good framework, however, I'm unsure of how to progress. I
intend to have a class to represent the actual DBF files, and I would
expect to have an __init__ method to be called when creating a new
instance. When I first started, I included a filename as a parameter
that would be used to open an existing DBF file. Next I decided to add
the ability to create a new DBF file. This method needs additional
parameters (such as the field definitions), and, while in some other
languages, I could provide 2 versions of the constructor (overload it if
I'm using the right terminology), and the compiler would use the
appropriate one, things don't seem to work that way in Python. 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
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

# open existing file
f1 = dbf()
f1 = dbf.Open('customer.dbf')
# create a new file
f2 = dbf()
f2 = dbf.Create('states.dbf', [('StateCode', 'C', 2), \
('StateName','C',20)]
Or maybe there's a clean way to be able to 'bundle' the
initialization/construction into the Create & Open method calls. Thanks
for the help,

--
Greg

Jul 18 '05 #1
6 4559
Greg Brunet wrote:
...
instance. When I first started, I included a filename as a parameter
that would be used to open an existing DBF file. Next I decided to add
the ability to create a new DBF file. This method needs additional
parameters (such as the field definitions), and, while in some other
languages, I could provide 2 versions of the constructor (overload it if
I'm using the right terminology), and the compiler would use the
appropriate one, things don't seem to work that way in Python. 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.
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)

# 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.
# create a new file
f2 = dbf()
f2 = dbf.Create('states.dbf', [('StateCode', 'C', 2), \
('StateName','C',20)]


Ditto.
Alex

Jul 18 '05 #2
Hello Greg,
When I first started, I included a filename as a parameter
that would be used to open an existing DBF file. Next I decided to add
the ability to create a new DBF file. This method needs additional
parameters (such as the field definitions), and, while in some other
languages, I could provide 2 versions of the constructor (overload it if
I'm using the right terminology), and the compiler would use the
appropriate one, things don't seem to work that way in Python. 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
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:


I see two ways:
1. Module (not class) methods: db = opendb(..), db = createdb(...)
2. Passing keyword arguments.
def __init__(selfk, filename, **kw):
if kw.has_key(create):
....

I vote for the former.

HTH.
Miki
Jul 18 '05 #3
"Greg Brunet" <gr********@NOSPAMsempersoft.com> wrote in message news:<vj************@corp.supernews.com>...
I'm trying to write a package to handle working with DBase files.
There's enough different stuff in handling them (unfortunately) that I'm
not going to try to the interface DB-API 2.0 compliant - it'll be a
lower level wrapper around reading & writing the DBF files. In trying
to design a good framework, however, I'm unsure of how to progress. I
intend to have a class to represent the actual DBF files, and I would
expect to have an __init__ method to be called when creating a new
instance. When I first started, I included a filename as a parameter
that would be used to open an existing DBF file. Next I decided to add
the ability to create a new DBF file. This method needs additional
parameters (such as the field definitions), and, while in some other
languages, I could provide 2 versions of the constructor (overload it if
I'm using the right terminology), and the compiler would use the
appropriate one, things don't seem to work that way in Python. 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
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

# open existing file
f1 = dbf()
f1 = dbf.Open('customer.dbf')
# create a new file
f2 = dbf()
f2 = dbf.Create('states.dbf', [('StateCode', 'C', 2), \
('StateName','C',20)]


If I understand you correctly, this could be done with a metaclass
redefining the __call__ method and invoking Open or Create depending
on the number of the arguments:

class MetaTrick(type):
def __call__(cls,*args):
nargs=len(args)
obj=cls.__new__(cls)
if nargs==1:
obj.Open(*args)
elif nargs==2:
obj.Create(*args)
else:
raise 'Wrong number of arguments'

class dbf:
__metaclass__=MetaTrick
def Create(self, filename, fieldDefs):
print filename,fieldDefs
def Open(self, filename):
print filename

f1 = dbf('customer.dbf')
f2 = dbf('states.dbf', [('StateCode', 'C', 2),
('StateName','C',20)])
Alternatively, without metaclass, you could redefine the __new__ method
of the class and use a similar trick.
HTH,
Michele
Jul 18 '05 #4
Hi Miki:
I see two ways:
1. Module (not class) methods: db = opendb(..), db = createdb(...)
2. Passing keyword arguments.
def __init__(selfk, filename, **kw):
if kw.has_key(create):
....

I vote for the former.

Thanks for the response. I lie the first also - what function is being
called is more clear than option 2 which would require extra tests
(depending on how many __init__ variations there are). If I can
understand the staticmethod stuff that Alex mentioned in his message, I
may try that path , since I'd like to have the methods actually in the
class definition, but defining them in the module itself is definitely a
good option. Thanks,
--
Greg

Jul 18 '05 #5
Hi Michele

"Michele Simionato" <mi**@pitt.edu> wrote in message
news:22*************************@posting.google.co m...
If I understand you correctly, this could be done with a metaclass
redefining the __call__ method and invoking Open or Create depending
on the number of the arguments:

class MetaTrick(type):
def __call__(cls,*args):
nargs=len(args)
obj=cls.__new__(cls)
if nargs==1:
obj.Open(*args)
elif nargs==2:
obj.Create(*args)
else:
raise 'Wrong number of arguments'

class dbf:
__metaclass__=MetaTrick
def Create(self, filename, fieldDefs):
print filename,fieldDefs
def Open(self, filename):
print filename

f1 = dbf('customer.dbf')
f2 = dbf('states.dbf', [('StateCode', 'C', 2),
('StateName','C',20)])
Alternatively, without metaclass, you could redefine the __new__ method of the class and use a similar trick.
HTH,

Hmm - I see. That could work in this instance, but could get more
complex with a different combination of 'constructor' types. Since
python doesn't seem to handle this overloading for me automatically, I
don't think that it's worth the effort it to manually implement it -
it's likely to be a source of more work & errors down the road. I'm
kind of leaning to using the 'staticmethod' technique that Alex
mentioned. Thanks for another view on it - that (metaclasses) gives me
one more technique to use in the future,
--
Greg

Jul 18 '05 #6
In article <33**************************@posting.google.com >,
Miki Tebeka <te****@cs.bgu.ac.il> wrote:

1. Module (not class) methods: db = opendb(..), db = createdb(...)


Clarification: modules have functions, not methods
--
Aahz (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/

This is Python. We don't care much about theory, except where it intersects
with useful practice. --Aahz
Jul 18 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Neil Zanella | last post by:
Hello, AFAIK the only way to initialize a reference variable defined inside a class is to initialize it in an initializer list. However, when there are multiple constructors, this means that the...
12
by: Sunny | last post by:
Hi All, I have a serious issue regarding classes scope and visibility. In my application, i have a class name "TextFile", and also a few other classes like "TotalWords", "TotalLines" and etc..,...
6
by: Baris | last post by:
Given the C# code below, can anyone think of a better class design? What really gets my goat is that the code within derived classes D1 and D2 is identical and in my mind should be refactored into...
6
by: JSheble | last post by:
I come from a Delphi background, and am currently trying to port or convert some of our Delphi classes to C#. I've got a good handle on basic class design, but am a bit lost with some of the more...
6
by: rodchar | last post by:
Hey all, I'm trying to understand Master/Detail concepts in VB.NET. If I do a data adapter fill for both customer and orders from Northwind where should that dataset live? What client is...
19
by: Chocawok | last post by:
Some of the classes in my app are graphical. To encapsulate the graphical side of things I had created a class called "sprite" which holds a bit map and knows how to draw itself etc. The...
2
by: nw | last post by:
Hi, I previously posted a question asking for suggestions on my class design. My original code consisted of a pure virtual base class Body which contained a number of integration algorithms...
5
by: pgrazaitis | last post by:
I cant seem to get my head wrapped around this issue, I have myself so twisted now there maybe no issue! Ok so I designed a class X that has a few members, and for arguments sake one of the...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.