FAQ
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

Search Discussions

  • Alex Martelli at Aug 7, 2003 at 11:00 am
    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
  • Greg Brunet at Aug 7, 2003 at 4:20 pm
    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
  • Miki Tebeka at Aug 7, 2003 at 11:49 am
    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
  • Greg Brunet at Aug 7, 2003 at 3:12 pm

    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
  • Aahz at Aug 7, 2003 at 5:46 pm
    In article <33803989.0308070349.29d8604e at posting.google.com>,
    Miki Tebeka wrote:
    1. Module (not class) methods: db = opendb(..), db = createdb(...)
    Clarification: modules have functions, not methods
    --
    Aahz (aahz at pythoncraft.com) <*> http://www.pythoncraft.com/

    This is Python. We don't care much about theory, except where it intersects
    with useful practice. --Aahz
  • Michele Simionato at Aug 7, 2003 at 3:15 pm
    "Greg Brunet" <gregbrunet at NOSPAMsempersoft.com> wrote in message news:<vj3dmc2s6218c1 at 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
  • Greg Brunet at Aug 7, 2003 at 4:28 pm
    Hi Michele

    "Michele Simionato" <mis6 at pitt.edu> wrote in message
    news:2259b0e2.0308070715.6e9ff32 at posting.google.com...
    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

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedAug 7, '03 at 2:17a
activeAug 7, '03 at 5:46p
posts8
users5
websitepython.org

People

Translate

site design / logo © 2022 Grokbase