10

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 in a:
    pass

a[0]

What are the methods that must be implemented?

3
  • possible duplicate of Build a Basic Python Iterator Commented Oct 24, 2011 at 12:54
  • Check the Python documentation at docs.python.org/reference/… Commented Oct 24, 2011 at 12:56
  • 3
    This is not a duplicate of the linked question. Sequence, iterable and iterator are three different things in Python. Commented Oct 24, 2011 at 13:45

2 Answers 2

15

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.)

Sign up to request clarification or add additional context in comments.

1 Comment

Are you sure that the last two lines are correct? They seem really strange to me. I supposed you wanted to write print x on the last line.
8

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]

1 Comment

collections.Sequence has Been moved to collections.abc.Sequence more recent version of python.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.