Jumping around when assigning elements

Francis Avila francisgavila at yahoo.com
Mon Dec 15 23:37:53 EST 2003


Matthew Sims wrote in message
<1e963607.0312151857.186adaa8 at posting.google.com>...
>"Francis Avila" <francisgavila at yahoo.com> wrote in message
news:<vtsgvm4d0dk157 at corp.supernews.com>...
>> Matthew Sims wrote in message
>> <1e963607.0312151408.583221e6 at posting.google.com>...
>
>Here's how the program basically worked. It's for a Tape Library with
>a robot arm in the middle. There are 40 slots and each is represented
>as an element in the array. If a tape was in one of the slots, that
>element # corresponds to the slot # and the tape ID would show in that
>element. All other elements represented blank slots. This allowed me
>to control the robot arm to the exact slot a tape resides since all I
>had to do was look at any elements that had tape IDs assigned.

Ah, I see.  Well, that makes more sense.  In this case it's *not* so
clear-cut whether to use a list or a dict (or whatever).  A list is a
reasonable approach.

Right off the bat, I can think of a few:

- What you're doing now, but initializing an empty list to fixed length, eg,
tapearray = [None]*40.  Now just use it (no need to worry about magically
extending the list as you add to random slots), but make sure you don't
modify the list with insert, append, extend, pop, etc., etc.: only perform
operations on its members.

Python doesn't do the implicit thing, so you're often well off by
preinitalizing data structures, as here.  I simply say [None]*40 and your
entire original question disappears, because you were looking at the problem
in a perlish manner of "how do I use this array in a manner that doesn't
require me to declare its total size before I use it."  Explicit is better
than implicit.

- Using a dict with integer keys.  Because your tape array won't change in
size, and iterating over the whole thing looks to be the most common
operation (as opposed to random access), dict might not be the obvious
choice.  But dicts are more flexable, and make explicit the importance of
the index.  You don't need to initalize your dict because it will add
non-existent keys on assignment, but it's probably less of a hassle to do so
anyway, because it *will* raise a KeyError if you try to read a key it
doesn't have.  To get around this, you need to subclass dict and make a
(commonly reimplemented) DefaultDict subclass, or make sure you consistently
use the setdefault method of your dict.  I say just preinitalize the blasted
thing: tapearray = dict([(i, None) for i in range(40)]).

- Using a list of lists, with zeroth element of each sublist the slot
number.  Now you don't have to worry about preinitalizing the list or
keeping the tape slots in order.  I can't think of any advantage to this
approach, unless you need faster iteration with variable total length, and
don't need the slots to be ordered.  Probably just use a dict.

- Write a TapeSlot class, a TapeArray class, and a TapeArrayVisitor class.
(I'm kidding! Don't do this.)

Of course, you can mix-and-match as your requirements demand.  If slots need
more status information, you could use a dict of lists or a list of lists.
If slots have a set of operations proper to them, you can use a list of
TapeSlot objects; or you could wrap the interface to the tapearray in a
TapeArray class, and make slot access a hidden implementation detail.

>So far the only way I could get this to work in Python was to insert
>"" to represent an empty slot. But Python counts "" when I want to see
>how many tapes are currently taking up slots "len(SLOTS)". It would
>always show 40. So I now know that I need to write code to tell Python
>not to count "". Not too difficult.

Not at all:

len([tapeID for tapeID in tapearray if tapeID])

"If the item in tapearray is True (in a boolean context, '' is False) append
that item to a new list, then find the length of this new list."

>
>I guess I'm realizing how I need to approach Python as my first OO.
>I'm re-writing the script as sort of a training. The program works
>flawlessly in Perl, I'm just doing it to learn. So far it has taken
>less lines of code in Python to perform the same tasks in Perl...up
>til this point. ;)

Unless you're doing relatively complex things that require a rich set of
data/semantics for tape slots and/or tape arrays, there's no reason to start
using objects to represent them: "Simple is better than complex."  Some
people get drunk on OO.  OO is useful, but can also add unnecessary
complexity and obscure what you're doing behind too many layers of
abstraction.

Finally, don't do line-of-code comparisons between Python and perl.  Python
may be brief, but it is *not* terse, and will choose clarity over
more-magic-per-line.  List comprehensions excepted. ;)

Ugh, I talk too much.  Well, hope you like Python!
--
Francis Avila





More information about the Python-list mailing list