When to use classes?
herzog at online.de
Sun Mar 5 13:37:01 CET 2000
Scott Bahling <sbahling at pitnet.net> writes:
> I am just starting to use python and I love it so far.
> I have a couple of philosophical questions about OOP programming with
> First: When and when not to create a new class? An example would be if I
> have a class for a Polygon, I need to store a set of points defining the
> polygon object. One method would be to store a list of tuples containing
> the polygon's points. If I want to access the individual x and y coords
> of each point, I end up with code that looks like:
> firstxcoord = poly.points
> firstycoord = poly.points
A more pythonic way to write this is
firstxcoord, firstxcoord = poly.points
which is even easier to read IMO than..
> Or I could create a Point class and use a list of them in the Polygon
> class. Then I would have code that looks like:
> firstxcoord = poly.points.x
> firstycoord = poly.points.y
.. this version.
> The second piece of code is easier to read. But lets say that this Point
> class has no other purpose but to contain two numerical values; is the
> use of a Point class overkill? Is there a 'rule of thumb' for when to
> create a new class?
Using a point class has some advantages. You could e.g. overload the '-'
operator and the abs function, i.e. implementing the __sub__ and __abs__
methods, and then use
dist = abs(poly.points - poly.points)
to compute the distance between two points.
Implementing __add__, __getitem__ and other special methods would also
be useful. With __getitem__ the x, y = point idiom would also work
> Second: What is the general consensus about accessing instance variables
> directly like myobj.x=10 vs. through methods like myobj.setx(10). The
> first method is quicker/easier to code, but is it "bad" coding? Does
> anyone even care?
That depends :)
First, I think you have to distinguish between reading attributes and
setting attributes. Reading attributes is OK, IMO, in some cases. E.g.
in the point class its quite natural to have x and y attributes and
access them directly, unless you want to keep the option to change the
representation from cartesian coordinates to polar coordinates or some
such, but even then you could use __getattr__ to compute x and y on the
Setting attributes from outside the class is much harder to justify,
IMO, because some objects should better not be changed in placed and
some objects want to keep some additional state that depends on the
values of certain attribute and bypassing the normal access functions
would cause trouble (you could use the __setattr__ method to control
this, but I think that route should be avoided if possible).
To illustrate this a bit, the point objects are a good example for
immutable objects. If you overload the arithmetic operators they behave
very much like numbers and you inevitable end up treating them like that
which means among other things that you don't worry about different
parts of the code referencing the same point objects. If then modify
these objects in place very subtle bugs occur.
That was at least my experience when I started to write Sketch. I indeed
had a point class that overloaded the operators and that I modified in
place. I ended up explicitly copying points whenever I needed to store
them e.g. in instance variables, just to make sure they weren't changed
behind the object's back. In the end I implemented the point objects in
C and they're immutable now and you can read their x and y attributes
Some rules of thumb:
- if the objects have an obvious simple inner structure it might be OK
to read attributes directly.
- If the objects are complex or have no obvious inner structure use
methods to access attributes.
- If it's natural or desired to pass objects around and to store them
in several places without worrying about sharing (like e.g. numbers
or strings), don't ever modify the objects in place.
- When in doubt, use access methods.
Bernhard Herzog | Sketch, a drawing program for Unix
herzog at online.de | http://sketch.sourceforge.net/
More information about the Python-list