En Mon, 05 May 2008 20:34:32 -0300, John Schroeder <[EMAIL PROTECTED]> escribió:

Basically I have some classes like this:


###############################################################################
# 0x01: ModeCommand
###############################################################################
class ModeCommand:
    """This is the Mode Command Packet class."""
    def __init__(self, mode, command, id=0x01):
        """The unspecial init function."""
        self.mode = mode
        self.command = command
        self.id = id

    def RawData(self):
        return [self.id, self.mode, self.command]

    def __getitem__(self, index):
        """[] operator (read): indexes from the byte data."""
        return self.RawData()[index]

    def __str__(self):
        """Print a nice thing."""
        string = "Mode = %d\n" % self.mode + \
                 "Command = %d\n" % self.command + \
                 "ID = %d\n\n" % self.id
        return string

###############################################################################
# 0x02: CallRequest
###############################################################################
class CallRequest:
    """This is the Call Request Packet class.  (Look familiar?)"""
    def __init__(self, service_number, id=0x02):
        """The unspecial init function."""
        self.service_number = service_number
        self.id = id

    def RawData(self):
        return [self.id, self.service_number]

    def __getitem__(self, index):
        """[] operator (read): indexes from the byte data."""
        return self.RawData()[index]

    def __str__(self):
        """Print a nice thing."""
        string = "Service Number = %d\n" % self.service_number + \
                 "ID = %d\n\n" % self.id
        return string


###############################################################################
# Test Code
###############################################################################
x = ModeCommand(mode=1, command=0)
print x[:]
print x
y = CallRequest(service_number=2001)
print y[:]
print y


Which is ok but I had to do this over 100 times.  It is difficult to
maintain and no one else can understand what the heck I did here. So I was
trying to look a metaclasses to do something fancy like this:

You don't need a metaclass, nor a class factory. You only need a base class. __getitem__ is the same on both classes, and presumably on all: move it to the base class. And the only difference between both versions of __init__, RawData and __str__ is the name and order of the attributes: let's make them a parameter, a class attribute. The default id attribute may be a class attribute too. So in principle, if you have the right base class, the subclasses could be defined as simply as:

class ModeCommand(Base):
    """This is the Mode Command Packet class."""

    parameters = "mode command id".split()
    id = 0x01

class CallRequest(Base):
    """This is the Call Request Packet class.  (Look familiar?)"""

    parameters = "service_number id".split()
    id = 0x02

and that's all. Now we have to write the Base class:

class Base(object):
    parameters = None # redefined in all subclasses
    id = None

    def __init__(self, **kw):
        assert self.parameters is not None # must be redefined
        for name in kw:
            if name in self.parameters:
                setattr(self, name, kw[name])
            else:
                raise NameError, "unknown parameter: %s" % name
        assert self.id is not None # must be redefined

    def RawData(self):
        return [getattr(self, name) for name in self.parameters]

    def __getitem__(self, index):
        return self.RawData()[index]

    def __str__(self):
        return '\n'.join(
                     ["%s = %r" % (name, getattr(self, name))
                      for name in self.parameters])

py> x = ModeCommand(mode=1, command=0)
py> print x[:]
[1, 0, 1]
py> print x
mode = 1
command = 0
id = 1
py> y = CallRequest(service_number=2001, id=13)
py> print y[:]
[2001, 13]
py> print y
service_number = 2001
id = 13

(the convention is to use lowercase names for attributes: rawdata instead of RawData)

--
Gabriel Genellina

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to