On Tue, 30 Jan 2007 21:15:53 -0800, manstey wrote: > Hi Ben, > > Could I also do something like the following? What does it mean to > store the parent class as a private variable in the child class?
What it means is that references to "self.__data" (note the TWO leading underscores) in your code below are mangled by Python to be "self._CacheProperty__data__" instead. This gives you a weak form of "private" variable, good for annoying people and yourself, possibly okay to help prevent many accidental name clashes, but not much else. On the other hand, references to "self._parent" (note only ONE leading underscore) is a convention. It is like putting a comment "Private, don't touch" in your code. It isn't enforced by Python. That's usually a good thing. > class CacheProperty(object): > def __init__(self, obj, parent, properties=None): > self.__data = obj > self._parent = parent > if properties is None: > properties = {} > self._accumulate_properties(properties) > > > def _accumulate_properties(self, properties): > self.properties = [] Probably better to put that in the __init__ method, otherwise if somebody runs instance._accumulate_properties(...) again, it will have the side-effect of throwing away whatever was already in instance.properties. Some people might argue that if someone runs a private method like _accumulate_properties, they deserve whatever bad things happen to them. But I say, well, sure, but why *design* your method to break things when called twice? Who knows, maybe you'll decide you want to call it twice yourself. > for key, val in properties.iteritems(): > setattr(self, key, val) > self.properties.append(key) If I am reading this correctly, self.properties is almost the same as self.__dict__.keys() only missing some values. > def __getattr__(self, name): > return getattr(self.__data, name) Okay, let's see how this works. child = CacheProperty([1,2,3], PARENT, {"food": "eggs", "colour": "green"}) # child.__data is the list [1,2,3] # child._parent is PARENT (whatever that is) # child.properties is the list ['food', 'colour'] Now, if I say: child.__len__() => returns 3 child.index(2) => returns 1 That's just straight-forward delegation to the "obj" argument stored in data. But when I say: child.set('foo') expecting to have the following method called: > def set(self, property): > return self._parent.set(property) oops! It gets delegated to obj instead of the parent. > the set function allows us to call the parent set function within the > child, which is what we need to do. Why not do this? instance._parent.set('foo') No mess, no fuss, bug-free, and self-documenting. -- Steven D'Aprano -- http://mail.python.org/mailman/listinfo/python-list