On Aug 2, 6:49 am, [EMAIL PROTECTED] wrote: > Hi all, > > It's possible that I'm missing the obvious -- I've been up for over 24 > hours and I'm most likely dehydrated from mass coffee intake, but I > figure many people in similar circumstances will be searching > comp.lang.python one day, so here goes! > > class LibraryClass(object): > > """ > A class whose implementation is out of my hands. > """ > > def __init__(self): > """ > Follows good dynamic-language form and binds all instance > variables at initialization time. > """ > # Omitted: complex initialization functionality. > self.useful_attr = None > > class MyInheritedClass(LibraryClass): > > """ > My refinement of the functionality offered by the LibraryClass. I > now want the instance to initialize with a reference to an > external > object, and the useful_attr defined in the superclass will now > reference an attribute of that external object via fget. > > Changing the attribute of the external object has undefined > behavior, so I want to omit an fset in the property declaration; > however, I have to provide some way for the superclass to > initialize useful_attr -- I can't change the superclass' code, as > it > resides in a library that is out of my hands. > """ > > def __init__(self, external_obj): > LibraryClass.__init__(self) > self._external_obj = external_obj > > def get_useful_attr(self): > return self._external_obj.proxy_useful_attr > > useful_attr = property(fget=get_useful_attr) > > def test(): > class _Fake(object): > pass > external_obj = _Fake() > external_obj.proxy_useful_attr = 12 > spam = MyInheritedClass(external_obj) > > if __name__ == '__main__': > test() > EOF > > If you're one of those people who doesn't like laboriously reading > contrived examples (elitists ;) I'll boil it down for you: Library > class initializes some attribute, but derived class wants to eliminate > fsets for said attribute. As a result, our ideal solution > > Of course, this means that the derived class will raise an error in > some circumstances where the base class wouldn't (when you're setting > that attribute), but one can assume that the inheritance is > worthwhile. > > How do I come up with silly solutions to circumvent this? Let me count > the ways... > > 1. So-and-so: make an fset that does nothing. This ignores (what > should be) errors in code that uses MyInheritedClass in an attempt to > accommodate a useless statement in the base class -- surely non-ideal. > 2. The ugly one: since you can probably view the library, copy and > paste the complex initialization functionality in the above, but leave > out the bad statement. This not only forfeits the ideals of > inheritance, but makes you totally incompatible with future library > changes. > 3. Cheerleader: Pure evil. On top of the ugliness of 2, you assume > that across library revisions the indenting won't change and that the > troublesome statement will remain on the same line, and pull off one > of these babies: > > def super_evil_test(): > from inspect import getsourcelines > exec(''.join([line[4:] for line in > getsourcelines(LibraryClass.__init__)[0][:-1]])) > LibraryClass.__init__ = __init__ > test() # Passes, but several angels no longer get their wings > > Totally kidding, everybody! I hope Guido doesn't read this thread... > > And this concludes the sleep deprived rambling that follows the > somewhat interesting case in point. Thoughts?
I'm sorry -- the solution was not /enough/ coffee. Got another cup and sat down with the type/class unification doc, and found this thought- stimulating portion: http://www.python.org/download/releases/2.2/descrintro/#property If you want to override the __get__ operation for properties when used as a class attribute, you can subclass property - it is a new-style type itself - to extend its __get__ method, or you can define a descriptor type from scratch by creating a new-style class that defines __get__, __set__ and __delete__ methods. ... The get method won't be called when the property is accessed as a class attribute (C.x) instead of as an instance attribute (C().x). Seeing as how property is just a wrapper class, we don't need to declare it in the class body, though it /is/ the convention and the way it's done in all the docs I've seen. We fix our inherited class to be the following: [snip] class MyInheritedClass(LibraryClass): """ My refinement of the functionality offered by the LibraryClass. I now want the instance to initialize with a reference to an external object, and the useful_attr defined in the superclass will now reference an attribute of that external object via fget. Changing the attribute of the external object has undefined behavior, so I want to omit an fset in the property declaration; however, I have to provide some way for the superclass to initialize useful_attr -- I can't change the superclass' code, as it resides in a library that is out of my hands. """ def __init__(self, external_obj): LibraryClass.__init__(self) self.useful_attr = property(fget=self.get_useful_attr) self._external_obj = external_obj def get_useful_attr(self): return self._external_obj.proxy_useful_attr [snip] And it tests like a charm. -- http://mail.python.org/mailman/listinfo/python-list