[CentralOH] My First metaclass

Brandon Mintern bmintern at gmail.com
Tue Apr 15 21:51:05 CEST 2008


I've spent a while now trying to wrap my head around your code, and
I'm finally starting to see what's going on. I have a nagging feeling
that a similarly-elegant solution could be had without resorting to a
3-tier metaclass structure. That aside, I do have some comments on the
code you have provided.

The first thing that stuck out to me was the pervasive use of "<>". I
have never seen this used in any recently-written Python code, and
according to section 3.3 of the Python 2.5.1 docs, "!= is the
preferred spelling; <> is obsolescent." I say that not because it
adversely affects your code in this instance, but because I assume
that you do this in all your code, and it's generally considered bad
style. In fact, Guido removed it from Python 3000 back in 2006.


Another couple of lines that took me a second to figure out what was
going on was

self._data = [None] * len(self.__slots__)
self._data[:len(data)] = data

I generally try to avoid using the []*n construct because when used on
mutable types, it can really byte you. Consider:

> a = [[]]*3
> a[0].append(0)
> a
 -> [[0], [0], [0]]

Additionally, the two lines just weren't all that clear to me what
they were doing. Using islice, chain, and repeat from itertools, I
would personally do something like:

self._data = list(islice(chain(data, repeat(None)), len(self.__slots__)))

I think that would be an improvement because it makes it clear exactly
what _data is: a list of len(self.__slots__) elements composed of the
elements of data followed by repeated Nones. It has the additional
benefit of not first building a list of Nones, only to replace them
with different items on the next line.

I'm sorry to not have more comments on your actual metaclass
structure, but I fear I've already spent too much time on this reply.

Brandon

On Tue, Apr 15, 2008 at 9:06 AM, Mark Erbaugh <mark at microenh.com> wrote:
> I've been reading Wesley Chun's "Core Python Programming 2nd Edition"
>  and working on a large Python / wxPython / Postgres (psygopg2) database
>  application.  I wanted to simplify handling of the data retrieved from
>  the database, which may also be updated and written back to the
>  database.  psygopg2 is DBAPI 2 compliant which means and data from a
>  query is returned as a list (rows) of tuples (columns).  psycopg2 uses
>  the 'pyformat' style for parameter passing which expects a mapping to
>  provide parameters.
>
>  I wanted to make it easier to use the data from a query. I wanted to
>  track if the user had updated a row, and which columns in that row had
>  been updated. I needed to allow the data to track new rows that had been
>  inserted and rows that needed to be deleted.
>
>  Lastly, I wanted the data structure to be able to handle related "child"
>  data, such as lineitems on an invoice or purchase order.
>
>  I developed a system of classes that met these needs. However, it was
>  was a little cumbersome to use and I found myself putting off adding new
>  database functionality as getting everything working was tedious.
>
>  I looked at some of the Python recipes such as SuperTuple and DBTuple,
>  but these didn't quite meet my needs.
>
>  Then I read more about classes in Chun's book, especially the __slots__
>  parameter, descriptors and metaclasses.  I felt that that these might be
>  the key.  After a day of playing with things, I have a working class
>  that meets my requirements.  While the ancestor class uses some of these
>  advanced (to me) features, descendant classes are extremely simple, all
>  one needs to do is define the __slots__ attribute.  It meets my current
>  needs:
>
>  1) struct-like (x.colname) named column access. Note that slots are used
>  so a misspelled column name will trigger an exception
>
>  2) mapped access (x['colname'])
>
>  3) automatic tracking of update, insert and delete as well as tracking
>  which columns have been updated
>
>  4) inclusion of additional columns to handle related data.  For a parent
>  child relationship, this field could be a list containing instances of
>  another descendant class.
>
>  Here's what I came up with. Feel free to use it if appropriate, but
>  since this is my first foray into metaclasses, I would appreciate any
>  comments/criticisms.
>
>  Mark Erbaugh
[code snipped]


More information about the CentralOH mailing list