On 17 avr, 04:27, andrew cooke <[EMAIL PROTECTED]> wrote: > Hi, > > Thanks for the help a couple of days ago. I completed what I was > doing and wrote a summary which I've posted > athttp://acooke.org/cute/PythonMeta0.html > (it's kind of long to post here). I hope it might be useful to > someone else - it's complete code for a simple metaprogramming task > that uses metaclasses and descriptors. > > I'd also appreciate further feedback if I've done anything stupid or > if there's some interesting approach I've missed that might work > better.
1/ Not about metaprogramming, but ORMs. You write: """ I could use an existing ORM package, but my experience with them hasn't been that positive (in particular, I find SQL to be very useful and want to use it more than is normally possible with standard ORM). """ Makes me wonder if you really took a close-enough look at SQLAlchemy... (please ignore this if you did) 2/ about your code: if (self.ignore_identical is False or new_value is not obj._auto_write_dict[self.name]): Take care, 'is' is the identity test operator, not the equality test operator. I think you *really* want the equality operator here. If you don't understand why, here's a sample run that's worth a longer explanation: >>> a = "it's wrong" >>> b = "it's wrong" >>> a is b False >>> a == b True >>> c = 99999 >>> d = 99999 >>> c is d False >>> c == d True >>> 0 is False False >>> 0 == False True >>> Also, the parens are not needed, and boolean tests don't need to be that explicit (ie, you don't necessarily need to test a boolean expression against True or False). And, last point, double-negations can be harder to understand. May I suggest: if not (self.ignore_identical and new_value == obj._auto_write_dict[self.name]): 3/ code again: attr = getattr(obj.__class__, "%s%s" % (self.prefix, self.name), None) obj._auto_write_dict[self.name] = attr(obj, new_value) Three points here: - build the setter name once and "cache" it. It'll make your code more readable (and save a couple cycles) def __init__(self, name, ignore_identical=True, prefix='_set_'): self.name = name self.ignore_identical = ignore_identical self.prefix = prefix self.settername = "%s%s" % (self.prefix, self.name) then use self.settername in __set__ - retrieving the setter on the object (instead of it's class) would be more pythonic, and way simpler to read. - None is not callable, so you code will crash if the object doesn't define a setter. You can either test the return value of getattr against None, put a try/except around the call, or use an identity function as default value for getattr (which is what I'd do here) Fix: setter = getattr(obj, self.settername, lambda x : x) obj._auto_write_dict[self.name] = setter(new_value) About the article itself, I'd say it makes a good introduction to a common metaprogramming pattern, but you'd have to get the opinion of someone that has no experience with these topics. Ho, and yes : one day, you'll get why it's such a good thing to unite functions and methods !-) My 2 cents -- http://mail.python.org/mailman/listinfo/python-list