views:

121

answers:

3

I have a small Python program consisting of very few modules (about 4 or so). The main module creates a list of tuples, thereby representing a number of records. These tuples are available to the other modules through a simple function that returns them (say, get_records()).

I am not sure if this is good design however. The problem being that the other modules need to know the indexes of each element in the tuple. This increases coupling between the modules, and isn't very transparent to someone who wants to use the main module.

I can think of a couple of alternatives:

  1. Make the index values of the tuple elements available as module constants (e.g., IDX_RECORD_TITLE, IDX_RECORD_STARTDATE, etc.). This avoids the need of magic numbers like title = record[3].

  2. Don't use tuples, but create a record class, and return a list of these class objects. The advantage being that the class methods will have self-explaining names like record.get_title().

  3. Don't use tuples, but dictionaries instead. So in this scenario, the function would return a list of dictionaries. The advantage being that the dictionary keys are also self-explanatory (though someone using the module would need to know them). But this seems like a huge overhead.

I find tuples to be one of the great strengths of Python (very easy to pass compound data around without the coding overhead of classes/objects), so I currently use (1), but still wonder what would be the best approach.

+5  A: 

http://docs.python.org/library/collections.html#namedtuple-factory-function-for-tuples-with-named-fields

gnibbler
`namedtuple()` : exactly what I was looking for ! Thanks.
Rabarberski
Hmm, just found out that `namedtuple` isn't supported in Python 2.5 (they were added in 2.6), which I use for mac OS X compatibility. Perhaps I'll have to resort to using a class anyway...
Rabarberski
+4  A: 

i do not see any overhead or complexity in passing objects over tuples(tuples are also objects)

IMO if tuple serves your purpose easily use it, but as you have seen the constraints just switch to a class which represent your data cleanily e.g.

class MyData(object):
    def __init__(title, desc):
        self.title = title
        self.desc = desc

You need not add any getter or setter method .

Anurag Uniyal
I was indeed thinking about the overhead of getters and setters, but forgot that in Python this isn't strictly necessary.
Rabarberski
A: 

In those cases, I tend to use dictionaries. If only to have things easily understandable for myself when I come back a bit later to use the code.

I don't know if it's a "huge overhead". I guess it depends on how often you do it and what it is used for. I start off with the easiest solution and optimize when I really need to. It surprisingly seldom I need to change something like that.

Mattias Nilsson
The overhead would be in the dictionary keys being present in each 'record'. Since the number of records will, in my case, never be large (< 100) the overhead is indeed negligible, but it doesn't 'feel right'.
Rabarberski
I agree about the feeling. :) I don't know if I am damaged by C++/Java programming, but for some reason it feels better to have some sort of data class holding the values. Doing that also helps your IDE with code completion in some cases. :) The `namedtuple` suggestion from gnibbler seems like a good compromise though.
Mattias Nilsson
And the `namedtuple` documentation explicitly says: *Named tuple instances do not have per-instance dictionaries, so they are lightweight and require no more memory than regular tuples.*
Rabarberski