I am looking for a sample minimal example of a class that mimics an immutable sequence in Python.
class MySequence()
...
a = MySequence()
len(a)
for i
If you just want to be able to iterate over your sequence, you just need to implement the __iter__
method returning an iterable. The easiest way to do this is to create a generator using the yield
statement.
class MySequence(object):
def __iter__(self):
yield 1
yield 2
yield 3
for x in MySequence():
print x # prints 1, then 2, then 3
However, this will not enable things like MySequence()[1]
. For that you need to implement the __getitem__
method, and should probably implement __len__
as well.
class MySequence(object):
def __len__(self):
return 3
def __getitem__(self, key):
if key == 0:
return 1
elif key == 1:
return 2
elif key == 2:
return 3
else:
raise IndexError()
s = new MySequence()
for i in range(len(s)):
print s[i] # prints 1, then 2, then 3
for x in s:
print x # prints 1, then 2, then 3
Notice that I omitted __iter__
. As long as __getitem__
raises an IndexError
when you try to get a value that's out-of-bounds, Python can use it for iteration. (I could still include __iter__
if I wanted to be clearer, or wanted non-standard iteration behaviour.)
Adding to @Jeremy's answer: A popular check that a value is a general sequence is to use isinstance(value, collections.Sequence)
.
In order to make this true for your type it needs to inherit from collections.Sequence, and this actually provides the iterator (and some other useful functions) as mixins, as long as you provide the __len__
and __getitem__
functions.
Borrowing from @Jeremy's answer, an example class would look like:
import collections
class MySequence(collections.Sequence):
def __len__(self):
return 3
def __getitem__(self, key):
if key == 0:
return 1
elif key == 1:
return 2
elif key == 2:
return 3
else:
raise IndexError()
Examples of usage:
s = MySequence()
for i in range(len(s)):
print s[i] # prints 1, then 2, then 3
for x in s:
print x # prints 1, then 2, then 3
print isinstance(s, collections.Sequence) # prints True
print 1 in s # prints True
print list(reversed(s)) # prints [3, 2, 1]