Mike Meyer <[EMAIL PROTECTED]> wrote: ... > Take our much-abused coordinate example, and assume you've exposed the > x and y coordinates as attributes. > > Now we have a changing requirement - we want to get to make the polar > coordinates available. To keep the API consistent, they should be > another pair of attributes, r and theta. Thanks to Pythons nice > properties, we can implement these with a pair of getters, and compute > them on the fly. > > If x and y can't be manipulated individually, you're done. If they > can, you have more work to do. If nothing else, you have to decide > that you're going to provide an incomplete interface, in that users > will be able to manipulate the object with some attributes but not > others for no obvious good reason. To avoid that, you'll have to add > code to run the coordinate transformations in reverse, which wouldn't > otherwise be needed. Properties make this possible, which is a great > thing.
Properties make this _easier_ (but you could do it before properties were added to Python, via __setattr__ -- just less conveniently and directly) -- just as easy as setX, setY, setRho, and setTheta would (in fact, we're likely to have some of those methods under our properties, so the difference is all in ease of USE, for the client code, not ease of IMPLEMENTATION, compared to setter-methods). If we keep the internal representation in cartesian coordinates (attributes x and y), and decide that it would interfere with the class's usefulness to have rho and theta read-only (i.e., that it IS useful for the user of the class to be able to manipulate them directly), we do indeed need to "add code" -- the setter methods setRho and setTheta. But let's put that in perspective. If we instead wanted to make the CoordinatePair class immutable, we'd STILL have to offer an alternative constructor or factory-function -- if it's at all useful to manipulate rho and theta in a mutable class, it must be at least as useful to be able to construct an immutable version from rho and theta, after all. So, we ARE going to have, say, a classmethod (note: all the code in this post is untested)...: class CoordinatePair(object): def fromPolar(cls, rho, theta): assert rho>=0 return cls(rho*math.cos(theta), rho*math.sin(theta)) fromPolar = classmethod(fromPolar) # etc etc, the rest of this class well, then, how much more code are we adding, to implement setRho and setTheta when we decide to make our class mutable? Here...: def setRho(self, rho): c = self.fromPolar(rho, self.getTheta()) self.x, self.y = c.x, c.y def setTheta(self, theta): c = self.fromPolar(self.getRho(), theta) self.x, self.y = c.x, c.y That's the maximum possible "difficulty" (...if THIS was a measure of real "difficulty" in programming, I doubt our jobs would be as well paid as they are...;-) -- it's going to be even less if we need anyway to have a method to copy a CoordinatePair instance from another, such as def copyFrom(self, other): self.x, self.y = other.x, other.y since then the above setters also become no-brainer oneliners a la: def setRho(self, rho): self.copyFrom(self.fromPolar(rho, self.getTheta())) and you might choose to further simplify this method's body to self.copyFrom(self.fromPolar(rho, self.theta)) since self.theta is going to be a property whose accessor half is the above-used self.getTheta (mostly a matter of style choice here). Really, I don't think this makes a good poster child for your "attribute mutators make life more difficult" campaign...;-) Alex -- http://mail.python.org/mailman/listinfo/python-list