Как реализовать минимальный класс, который ведет себя как последовательность в Python? - PullRequest
7 голосов
/ 24 октября 2011

Я ищу образец минимального примера класса, который имитирует неизменную последовательность в Python.

class MySequence()
    ...

a = MySequence()

len(a)

for i in a:
    pass

a[0]

Какие методы должны быть реализованы?

Ответы [ 2 ]

11 голосов
/ 24 октября 2011

Если вы просто хотите иметь возможность перебирать вашу последовательность, вам просто нужно реализовать метод __iter__, возвращающий итерацию. Самый простой способ сделать это - создать генератор с помощью оператора yield.

class MySequence(object):
    def __iter__(self):
        yield 1
        yield 2
        yield 3

for x in MySequence():
    print x # prints 1, then 2, then 3

Однако, это не включит такие вещи, как MySequence()[1]. Для этого вам необходимо реализовать метод __getitem__, и, вероятно, также следует реализовать __len__.

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

Обратите внимание, что я пропустил __iter__. Пока __getitem__ поднимает IndexError, когда вы пытаетесь получить значение, которое выходит за пределы, Python может использовать его для итерации. (Я все еще мог бы включить __iter__, если бы я хотел быть более понятным или хотел нестандартного поведения итерации.)

0 голосов
/ 14 апреля 2019

Добавление к ответу @ Джереми: популярная проверка того, что значение является общей последовательностью, заключается в использовании isinstance(value, collections.Sequence).

Для того, чтобы это верно для вашего типа, оно должно наследоваться от collections.Sequence, и это фактически обеспечивает итератор (и некоторые другие полезные функции) в качестве миксинов, если вы предоставляете функции __len__ и __index__.

Заимствование из ответа @ Jeremy,пример класса будет выглядеть так:

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

Примеры использования:

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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...