[Tutor] Still on Linked Lists [References, UserDict]

Daniel Yoo dyoo@hkn.eecs.berkeley.edu
Wed, 4 Apr 2001 00:26:36 -0700 (PDT)


On Tue, 3 Apr 2001, VanL wrote:

> I know that all of you are probably going to groan, but I really don't
> have any special affection for linked lists.  I am just trying to use
> them as a tool to learn stuff.  

No prob, don't worry about it.



> That said, I have two questions.  I will raise one in this email and the
> other in the next.
> 
> 1.  I put together a new implementation of a linked list class:
> 
> class LinkedList2:
>     
>     """ This class provides a generic node for linked lists.  Other
> python classes or
>     objects can inherit from this class to get the ability to represent
> themselves as
>     a linked list. """
> 
>     def __init__(self, name, data=None, object=None):
>         self = (name, data, object)


There's something here that you'll need to fix; unfortunately, the tuple
assignment here doesn't quite work, since self is more like a dictionary
than a list.  To set things inside self, we need to use the period scoping
operator (".").  For example, we'll want something like:

    def __init__(self, name, data=None, object=None):
        self.name, self.data, self.object = name, data, object

which will do the assignment.



What you had before did something different: it assigned the name "self"
to the tuple (name, data, object), which won't work.  Let's take a
look again:

>     def __init__(self, name, data=None, object=None):
>         self = (name, data, object)

It's the situation that Shelia King ran across with references: here,
we're saying that, locally, "self" now stands for a tuple of 3 elements,
which is certainly not what we want; we want to change the object that
"self" refers to, and not redirect "self" to a new object.


In any case, with those changes in mind, the accessor functions will need
to change, since we're using "self" this way:


>     def next(self):
>          return self[2]

becomes:

    def next(self):
        return self.object


>     def label(self):
>         return self[0]


becomes:

    def label(self):
        return self.name

etc.



> However, this doesn't work:
> 
> >>> from LinkedList2 import *
> >>> this = LinkedList2('thisname')
> >>> that = LinkedList2('thatname', 'somedata', this)
> >>> theother = LinkedList2('theothername', 'someotherdata', that)
> >>> print theother
> 
> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
>   File "LinkedList2.py", line 32, in __str__
>     print self[0], self[1], self[2]
> AttributeError: 'LinkedList2' instance has no attribute '__getitem__'

By default, we need to change the components of self using that
period-scoping syntax.  Indexing on "self" doesn't work by default; that's
where that AttributeError is coming from. However, it is possible to do
this, but it takes some extra work by using UserDict:

    http://python.org/doc/current/lib/module-UserDict.html

If you use UserDict, then your code will work:

###
import UserDict

class LinkedList2(UserDict.UserDict):
    def __init__(self, name, data=None, object=None):
        UserDict.UserDict.__init__(self)
        self[0], self[1], self[2] = name, data, object

    # and everything else stays the same.
###

But you'll need to experiment with UserDict a bit, just to see how it
works.  Hope this helps!