subclassing list

S

spike

I've googled like crazy and can't seem to find an answer to why this
isn't working.

I want to create a custom list class that acts as a circular list.

ie: my_list = (0, 1, 2)

how I want it to behave:

my_list[0] -> 0
my_list[1] -> 1
my_list[2] -> 2
my_list[3] -> 0
my_list[4] -> 1
....etc

so, what I've tried to do is:

def circular_list(list):
def __getitem__(self, i):
if (i >= len(self)):
return self[i % len(self)]
else:
return self

items = circular_list(range(8))

however, when I want to iterate over it with a for statement, I get:

TypeError: iteration over non-sequence

what am I missing?

thanks!
 
R

Robert Kern

spike said:
I've googled like crazy and can't seem to find an answer to why this
isn't working.

I want to create a custom list class that acts as a circular list.

ie: my_list = (0, 1, 2)

how I want it to behave:

my_list[0] -> 0
my_list[1] -> 1
my_list[2] -> 2
my_list[3] -> 0
my_list[4] -> 1
...etc

so, what I've tried to do is:

def circular_list(list):
def __getitem__(self, i):
if (i >= len(self)):
return self[i % len(self)]
else:
return self

items = circular_list(range(8))

however, when I want to iterate over it with a for statement, I get:

TypeError: iteration over non-sequence


You also need to post the code that raises the error, or no one else can
debug it.
what am I missing?

I have no idea why you get that error. I do not in Python 2.4.1.
However, I also don't get what you desire either. Iteration over lists
(and subclasses of list) hasn't used __getitem__ since Python 2.2.

http://www.python.org/doc/2.2/lib/typeiter.html

In [7]: class circular_list(list):
...: def __getitem__(self, i):
...: return list.__getitem__(self, i%len(self))
...:

In [8]: items = circular_list(range(8))

In [9]: for i in items:
...: print i
...:
0
1
2
3
4
5
6
7

In fact, if all you need is iteration, use itertools.cycle().

In [6]: itertools.cycle?
Type: type
Base Class: <type 'type'>
String Form: <type 'itertools.cycle'>
Namespace: Interactive
File:
/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/lib-dynload/itertools.so
Docstring:
cycle(iterable) --> cycle object

Return elements from the iterable until it is exhausted.
Then repeat the sequence indefinitely.

In [11]: class better_circular_list(circular_list):
....: def __iter__(self):
....: return itertools.cycle(list.__iter__(self))
....:

In [13]: bcl = better_circular_list(range(8))

In [14]: for i in bcl:
....: print i
....:
0
1
2
3
4
5
6
7
0
1
2
<etc.>

--
Robert Kern
(e-mail address removed)

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
 
J

John Machin

spike said:
I've googled like crazy and can't seem to find an answer to why this
isn't working.

I want to create a custom list class that acts as a circular list.

ie: my_list = (0, 1, 2)

Perhaps you mean [0, 1, 2]
how I want it to behave:

my_list[0] -> 0
my_list[1] -> 1
my_list[2] -> 2
my_list[3] -> 0
my_list[4] -> 1
...etc

so, what I've tried to do is:

def circular_list(list):
def __getitem__(self, i):
if (i >= len(self)):
return self[i % len(self)]
else:
return self

items = circular_list(range(8))

however, when I want to iterate over it with a for statement, I get:

TypeError: iteration over non-sequence

what am I missing?


0.1 Elementary debugging, like a "print" statement after "items = cir......"

0.2 pychecker -- These warning messages might have given you a clue:

spike.py:2: Local variable (__getitem__) not used
spike.py:2: Parameter (list) not used

1. A "class" statement. Your *function* circular_list returns None,
which is a non-sequence.

2. A definition of what "in" a circular_list really means: in your
example, 7 is obviously "in", but is 15 "in" or "not in"? Do you want
"if x in a_circ_list" to be compatible with "for x in a_circ_list"?

3. An abhorrence of superfluous parentheses.

4. Battle-scars: you haven't been hit with "RuntimeError: maximum
recursion depth exceeded" before, have you? After you've done
s/def/class/ and put in some elementary test statements like "print
items[3]", run it again and seen what happens, Google search for
"__getitem__ infinite recursion" in this newsgroup.

HTH,
John
 
S

spike grobstein

You also need to post the code that raises the error, or no one else can
debug it.

sorry, I thought I had pasted that line in there, but I guess I missed
it. Here's the full code (after modifying it slightly based on your
post):

#! /usr/bin/env python

def circular_list(list):
def __getitem__(self, i):
return list.__getitem__(self, i % len(self))

items = circular_list(range(8))

for i in items:
print i

[/end code]

spike@flaphead ~/tests/afx-view $ ./circular.py
Traceback (most recent call last):
File "./circular.py", line 10, in ?
for selected in items:
TypeError: iteration over non-sequence

if I just try to call:

print items[12]

I get this error:
spike@flaphead ~/tests/afx-view $ ./circular.py
Traceback (most recent call last):
File "./circular.py", line 9, in ?
print items[12]
TypeError: unsubscriptable object

I'm using python 2.3.5
 
R

Robert Kern

spike said:
debug it.

sorry, I thought I had pasted that line in there, but I guess I missed
it. Here's the full code (after modifying it slightly based on your
post):

#! /usr/bin/env python

def circular_list(list):
^^^
As John pointed out, this is part of the problem, but as I pointed out,
that's not the last of the problems with the code.

--
Robert Kern
(e-mail address removed)

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top