I have been scripting with Python for a few years but I just recently decided to start using some OOP to make my life a bit easier. Although I've read many examples and some chapters and websites, some of the most rudimentary basics still elude me. Here is an example that is causing me trouble. I could use a nudge in the right direction.

What I'd like to do is define my data structure - which happens to be a complicated list of lists. I would like the class Superlist to allow me to access certain elements of the structure, so I don't have to keep looking up where each item is stored in the hierarchy. But I also still want access to the original list. I hope that makes sense. I assume I'm making some fundamental mistake in how I approach this problem, but I hope there is an easy way to have it explained to me.

Here is a very simplified example that illustrates the problem.

class Superlist(list):
        def __init__(self, list):
             self.a = list[1][0]
             self.b = list[2][1]

    somelist = [[1,2,3],[4,5,6],[7,8,9]]

    somelist = Superlist(somelist)

    >somelist.a  # this works
    >4
    >somelist.b # this works
    >7
    >somelist # wait a minute - why can't I access the original list?
    >[]
    >somelist[0] # this should give me [1,2,3] - why doesn't it?
    IndexError: list index out of range

I'd like to still be able to use somelist as a list structure. But it seems that once I define it as the Superlist, I lose that ability.

Well, walk through your code:

class Superlist(list):
        def __init__(self, list):
             self.a = list[1][0]
             self.b = list[2][1]

    somelist = [[1,2,3],[4,5,6],[7,8,9]]

    somelist = Superlist(somelist)

At line 8, you create a new Superlist object. This creates a new list [], and then calls __init__. At init, you create two new properties of the new list, a and b. a is assigned to 4, b to 7. Then it returns.

At what point do you assign the values from the original somelist to the values in your Superlist? Never. So Python obligingly assigns somelist to be an empty list with two extra properties a and b. :)

One thing that makes this confusing is that superclassing existing basic types -- int, tuple, list, etc. -- is harder than creating objects. For one thing, the constructor should be __new__ instead of __init__. For another, the basic types are pretty good as is.

So what about something like this:

somelist = [[1,2,3],[4,5,6],[7,8,9]]
>>> mysuper = SuperList(somelist)
>>> mysuper
<__main__.SuperList object at 0x00BFB770>
>>> mysuper.a
4
>>> mysuper.a = 5
>>> mysuper.value
[[1, 2, 3], [5, 5, 6], [7, 8, 9]]

Jeff

Jeff - Thanks for walking me through that. I think I understand. I added a 'value' line to my self declaration, and now I am able to get the values that way.

But I'm still wondering how I can set this up in order to be able to access the original list?

Like this:

1. Define my list
2. Extend the function of list with Superlist
3. Access data elements with the new functionality in Superlist
4. Still access list the "old fashioned way"

What I'd like to be able to do is:

class SuperList(list):
	def __init__(self,list):
	        self.d = list[1][1]
		self.value = list

test = []
mylist = [[1,2,3],[4,5,6],[7,8,9]]
test.append(SuperList(mylist))

>test[0] # this does not work
>[[1,2,3],[4,5,6],[7,8,9]] # I want to get this, but I only get []
>test[0].d # this works
>4
>test[0].value # this works
>[[1,2,3],[4,5,6],[7,8,9]]

I know that test[0].value will do this. But what about accessing the whole data element (as I'm trying above). I think I understand "why" this does not work, but is there a way to do this? Again, sorry if this is an ignorant question - perhaps I am using this data constructor the wrong way. But hopefully there is a way to do what I want.

You're expectations are incorrect. You are doing this:

test = []
mylist = [[1,2,3],[4,5,6],[7,8,9]]
test.append(SuperList(mylist))

And are expecting this:

[[1,2,3],[4,5,6],[7,8,9]] # I want to get this, but I only get []

Shouldn't you be expecting:

[[[1,2,3],[4,5,6],[7,8,9]]]

You are appending to an empty list, another list - they won't merge but the argument to append will be a member in the original.

Maybe this _somewhat_ does what you need:

class SuperList():
        def __init__(self, lst):
                self.orig = lst
                self.d = lst[1][1]
        def __repr__(self):
                return str(self.orig)
        def __str__(self):
                return str(self.orig)

if __name__ == '__main__':
        t = []
        l = [[1,2,3],[4,5,6],[7,8,9]]
        t.append(SuperList(l))
        print t
        print t[0]
        print t[0].d

Output:

c:\>SuperList.py
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
5

HTH

You're expectations are incorrect. You are doing this:

test = []
mylist = [[1,2,3],[4,5,6],[7,8,9]]
test.append(SuperList(mylist))

And are expecting this:

[[1,2,3],[4,5,6],[7,8,9]] # I want to get this, but I only get []

Shouldn't you be expecting:

[[[1,2,3],[4,5,6],[7,8,9]]]

Correct.

Thank you very much for thinking through this with me.

Someone else suggested this simple maneuver that also seems to work:

class Superlist(list):
	def __init__(self, data):
		list.__init__(self, data)
		self.a = data[1][0]
		self.b = data[2][1]
		
l = [[1,2,3],[4,5,6],[7,8,9]]
test = Superlist(l)
>print test
>[[1,2,3],[4,5,6],[7,8,9]]
>print test.a
>4

Thanks for the patient help everyone. I'm making incremental progress with this.

class Superlist(list):
        def __init__(self, list):
             self.a = list[1][0]
             self.b = list[2][1]

    somelist = [[1,2,3],[4,5,6],[7,8,9]]

    somelist = Superlist(somelist)

    >somelist.a  # this works
    >4
    >somelist.b # this works
    >7
    >somelist # wait a minute - why can't I access the original list?
    >[]
    >somelist[0] # this should give me [1,2,3] - why doesn't it?
    IndexError: list index out of range

Hi, just a small tip, avoid using python keywords(eg: list) as identifiers in your programs.

katharnakh.

This article has been dead for over six months. Start a new discussion instead.