From: Jay L. <js...@js...> - 2001-12-31 20:06:35
|
One of the biggest peformance slowdowns in our current code is the extensive use of functions to set and get variable values. So anything that can take away some of the overhead is the way to go in my book. However, this is a very new capability in Python, and many people will not have 2.2 installed. Maybe we should wait a while before implementing this? My only issue is timing, not whether it is the right thing to do. Jay On Mon, 2001-12-31 at 00:54, Chuck Esterbrook wrote: > This topic is about the OO style employed by Webware. It is a long > topic and some may find it boring, but it affects the programmatic > interface to Webware, so I felt it should be posted to -discuss rather > than -devel for all to see. > > Here is the main point: > > With the advent of Python 2.2, we have the "properties style" as > described here: > http://www.python.org/2.2/descrintro.html#property > > Should Webware adopt the "properties style"? > > + Easy to read and write. > + Would make Webware source more Pythonic. > + Preserves "opaqueness". > + As fast as mixed style and faster than other styles. > - Existing code bases would require updates. > - Would required Python 2.2 OR that we provide the GetterSetter helper > for 2.0 and 2.1 users (with the understanding that performance might > take a dive for such users). > > > And here is a detailed background if you care to read further: > > When writing classes, the "mixed style" is to use both data attributes > and methods to access values: > > # Vector.py > class Vector: > def __init__(self): > self.x = self.y = 0 > def length(self): > return math.sqrt(self.x*self.x + self.y*self.y) > > # prog.py > v = Vector() > v.x = 1 > v.y = 4 > print v.length() > > I don't like the mixed style because if you switch a "foo" from a > method to an attribute or the other way around, you break the interface: > > class Vector: > def __init__(self): > self.x = self.y = 0 > def setX(self, x): > self.x = x > self._computerLength() > def setY(self, y): > self.y = y > self._computeLength() > def _computeLength(self): > self.length = math.sqrt(self.x*self.x + self.y*self.y) > > Now prog.py is broken simply because we wanted to compute the length > when X or Y are set (presumably we have determined it is asked for much > more frequently than it is altered). Setting X and Y broke because they > have to be methods now and asking for the length broke because it no > longer requires paren()s. > > (Note: These code examples are neither perfect, nor tested. They are > just to illustrate the issues.) > > Some people solve this by using the "getter-setter style": > > # GetterSetter.py > class GetterSetter: > > def __getattr__(self, name): > if not name.startswith('__'): > method = getattr(self, 'get_' + name, None) > if method: > return method() > raise AttributeError, name > > def __setattr__(self, name, value): > if not name.startswith('__'): > method = getattr(self, 'set_' + name, None) > if method: > method(value) > self.__dict__[name] = value > > # Vector.py > class Vector(GetterSetter): > > def __init__(self): > self.x = self.y = 0 > > def set_x(self, value): > self.__dict__['x'] = value > # ^^ use self.__dict__ to avoid infinite recursion to __setattr__ > self._computeLength() > > def set_y(self, value): > self.__dict__['y'] = value > self._computeLength() > > def _computeLength(self): > self.length = math.sqrt(self.x*self.x + self.y*self.y) > > Pros and cons of getter-setter style: > + Opaque: No code using Vector is broken. > + Concise: Vector users can conveniently avoid the extra parens and > "set" words and such that come with methods. eg. v.x = 5 and v.length > instead of v.setX(5) and v.length() > - Performance: Having experimented with this style in a recent project, > I found it could be a major source of slow down. Particularly, > __setattr__ adds a method call and extra Python byte code to every > attribute assignment. My program slowed down by at least 10X. > - Implementation: The use of self.__dict__['foo'] is ugly and > forgetting it results in infinite recursion (quickly spotted of course). > - Implementation: __getattr__ and __setattr__ are "asymmetric" in their > design. The first is called as a last resort, the other is always > called. This leads to some subtle issues in how you treat your > attributes. > > > Next we have the "encapsulation with methods" style which I guess I > took from Smalltalk & Objective-C and is the current Webware style. Use > methods for everything large and small. Pros and cons: > + No code breaks due to simple interface changes. > + Faster execution than the getter-setter style. > + Generally encourages more protection of the object's data attributes. > + Easy to understand > - Slower execution than the mixed style. > - More typing: obj.setFoo() obj.foo() self._foo > > > In a recent, private project I started with the getter-setter style and > found it more convenient than method encapsulation, but too expensive > performance-wise. I then scaled back to the mixed style, but with the > problems described above. Overall, I still liked the conciseness of > both styles. I felt like coding was quicker and just as readable. > > The properties style seems to give all the pros and only legacy-related > cons. See the beginning of the message. > > > Reactions? > > -Chuck > > _______________________________________________ > Webware-discuss mailing list > Web...@li... > https://lists.sourceforge.net/lists/listinfo/webware-discuss |