Class Factories in Python: How?

Warren Postma embed at geocities.com
Mon May 1 14:35:07 EDT 2000


Suppose I have a base class which handles a Binary Structures, in this case,
a series of Marshalled attributes, stored on disk as a marshalled array (so
it's fast, binary, and no field names are stored with each row).

Each type I want to create a new binary structure, I subclass it, but the
subclassing procedures are getting complex because there are so many
class-variables that need to be initialized.  So I decided to try to build a
class factory, like this:

This is a simplified (<100 lines) of something I'm trying to do that is
currently over 500 lines.

Warren

--- code snippet ---


# class factory example

import marshal
import string

def binstruct_lookup(attributes):
    "create a dictionary to lookup data row field orderings"
    n = 0
    dict1 = {}
    for n in range(0,len(attributes)):
        dict1[attributes[n]] = n
    return dict1

class marshalstruct:
    "a binary structure handler class - a simplified example"
    attributes = [ "a", "b", "c" ] # demo
    lookups = binstruct_lookup(attributes)
    fieldcount = len(attributes)
    def __init__(self):
        self.__dict__["values"] =
[None]*self.__class__.__dict__["fieldcount"]
    def as_string(self):
        return string.join(map(repr,self.__dict__["values"]), ", ")
    def marshal(self):
        return marshal.dumps(self.values)
    def unmarshal(self,binstr):
        self.__dict__["values"]= marshal.loads(binstr)
    def __getattr__(self,name):
        try:
            l = self.__class__.__dict__["lookups"][name]
        except:
            raise LookupError, "invalid field name "+name+" in binstruct."
        return self.__dict["values"][l]
    def __setattr__(self,name,value):
        try:
            l = self.__class__.__dict__["lookups"][name]
        except:
            raise LookupError, "invalid field name "+name+" in binstruct."
        self.__dict__["values"][l] = value

# Ugly way to Subclass:

#class marshalstruct2:
#    "subclass"
#    attributes = [ "d", "e", "f" ]
#    lookups = binstruct_lookup(attributes)
#    fieldcount = len(attributes)

# when I want to declare a specialization of the above class, I need
# to include all the right things, in the right order, to redefine
# variables at a class scope:


# A Nicer way? Is it possible?
# class factory to specialize the above class given some new attributes to
use:
def marshalstruct_factory(newattributes):
    class newclass(marshalstruct):
        attributes = newattributes
        lookups = binstruct_lookup(attributes)
        fieldcount = len(attributes)
    return newclass

# fails, attributes = newattributes doesn't work, probably because
# the above class scope doesn't admit the function parameters into its
scope.

#y = marshalstruct_factory(['test1','test2','test3'])



n = marshalstruct()

n.a = "a value"
n.b = "b value"
n.c = "c value"
try:
    n.d = "illegal!"
    print "Failure: Shouldn't get here!"
except LookupError:
    print "Working :illegal attribute name trapped"

print "dump fields separated by commas, as a string:"
print n.as_string()
print "Finished."








More information about the Python-list mailing list