tags:

views:

347

answers:

7

I am developing in python a file class that can read and write a file, containing a list of xyz coordinates. In my program, I already have a Coord3D class to hold xyz coordinates.

My question is relative to the design of a getCoordinate(index) method. Should I return a tuple of floats, or a Coord3D object?

In the first case, I get very low coupling, but then I will probably have to instantiate a Coord3D object with the obtained values anyway, although outside of the file class. In the second case, I will have the file class tightly coupled with the Coord3D class.

Please note that I think there's not a huge difference between the two solutions, but I would like to read your answer and the reason behind it.


Edit: to recap the answers I got until now, it looks like there's no clearcut choice. It has been said (appropriately) that python is not Java, and you don't need a specialized class for everything just because you need it by language architecture. In my case, however, I have the following conditions:

  1. I am working on a library, where the Coord3D object is used as is. Using it would increase the cohesiveness of my library, as the data types will be uniformly used.
  2. The Coord3D object has state and behavior. Indeed, the Coord3D object aggregate the coordinates and the units in a single entity. Operations among Coord3D objects will keep into account the potentially different units, and act accordingly.
  3. I can put centralize control code into the Coord3D class instantiation to refuse, for example, arrays of length 4, or non units. If I use a tuple, I cannot perform this check. Moreover, if a method accepts a Coord3D, is sort of guaranteed that it's well formed upfront (you could be bold and check for isinstance, or check the interface). A tuple can contain invalid data. Although python approach to error handling is done where the trouble happen, a class preventing me to have an xyz coordinate made out of three strings is somehow beneficial (correct me if wrong, please)

On the other hand, using a tuple has the following advantages:

  1. Less occupation of resources, quite critical in case of huge
  2. Simpler design. More classes means more complex design. A tuple is a standard data type which is well understood and can be unpacked easily. A personalized class is not.
  3. Using a tuple, the XYZFile class is totally decoupled from the rest of the library (because it does not use the Coord3D object). This means that it can be reused totally as an independent entity.

further comments very welcome!

+1  A: 

If it's only going to be used in your application, and if you're going to create a Coord3D instance with the values anyway, I'd just return a Coord3D instance to save you the effort. If, however, you have any interest in making this portable/general, return a tuple. It'll be easy to create a Coord3D anyway, using

c3d = Coord3D(*getCoordinate(index))

(assuming your constructor is Coord3D.__init__(self, x, y, z))

David Zaslavsky
Not sure I like this. It seems to expose some useless details. I think it would be better to pick one representation and stick to it.
S.Lott
A: 

I've asked myself the same question, albeit while doing 2D geometry stuff.

The answer I found for myself was that if I was planning to write a larger library, with more functions and whatnot, go ahead and return the Point, or in your case the Coord3D object. If it's just a hacky implementation, the tuple will get you going faster. In the end, it's just what you're going to do with it, and is it worth the effort.

sykora
+1  A: 

If other people (aside form yourself) will be using this class, it seems to me that returning an object would encourage some kind of uniformity in data types. If the Coord3D class has a method or property to access these coordinates as a tuple, then that still gives them that option, should they need it:

# get the object
coord_obj = my_obj.getCoordinate(my_index)
# get the tuple (for example, via a property named "coords")
coord_tup = my_obj.getCoordinate(my_index).coords
EvanK
+2  A: 

The more fundamental question is "why do you have Coord3D class?" Why not just use a tuple?

The general advice most of us give to Python n00bz is "don't invent new classes until you have to."

Does your Coord3D have unique methods? Perhaps you need a new class. Or -- perhaps -- you only need some functions that operate on tuples.

Does your Coord3D have changeable state? Hardly likely. An immutable tuple starts to look like a better representation than a new class.

S.Lott
In general I agree with your like of though. However, things are actually more complex. The Coord3D is pervasive in my code, also because it's associated with a Unum Unit.
Stefano Borini
I thought a mantra of Python was "Namespaces are one honking great idea -- let's do more of those!". Isn't a class better than just a group of related functions (that operate of tuples) better in this regard? Why do you have a requirement of state for a class? BTW, I am new to Python but I thought the idea of creating classes was a good thing -- not something to be avoided.
Trent
+1: Adding classes adds complexity, so avoid it unless there are real benefits (which I fail to see in this case).
nikow
A module is one kind of "namespace"; this is sometimes better than a class. In OO generally, a class encapsulates state and behavior. Where there are no state change, then... you don't have much of a class. In Python, you aren't obligated to create classes for every little thing like you are in Java. Particularly for every little immutable thing.
S.Lott
+1  A: 

Returning an object would be the best practice and would give you a better overall software design. I would recommend doing that

But still, keep in mind that creating/returning an object will take more processing time. It could change something if you do this operation a LOT and in that case you might need to think about it...

marcgg
+4  A: 

Compromise solution: Instead of a class, make Coord3D a namedtuple and return that :-)

Usage:

Coord3D = namedtuple('Coord3D', 'x y z')

def getCoordinate(index):
    # do stuff, creating variables x, y, z
    return Coord3D(x, y, z)

The return value can be used exactly as a tuple, and has the same speed and memory properties, so you don't lose any genericity. But you can also access its values by name: if c is the result of getCoordinate(index), then you can work with c.x, c.y, etc, for increased readibility.

(obviously this is a bit less useful if your Coord3D class needs other functionality too)

[if you're not on python2.6, you can get namedtuples from the cookbook recipe]

John Fouhy
+1  A: 

Take a look at Will McGugan's Gameobjects library. He has a Vector3 class that can be initialized with another Vector3 object, a tuple, individual float values, etc. I think this will answer your question ... plus you may end up just using his library as it's already optimized and has plenty of useful methods already.

Brandon Corfman