2015-08-21 3 views
0

Я пытаюсь написать класс итератора, который позволит мне указать длину шагов, которые делает итератор. Но я застрял в этой проблеме.Класс Iterator с указанной длиной шагов

Мой код:

class Reverse: 
    def __init__(self, data, step): 
     self.data = data 
     self.index = len(data) 
     self.step = step 
    def __iter__(self): 
     return self 
    def __next__(self, step): 
     if self.index <= 0: 
      raise StopIteration 
     self.index = self.index - self.step 
     return self.data[self.index] 

rev = Reverse('Drapsicle', 2) 

это показывает мне письмо 'л' всегда

rev.__next__(2) 

но петля дает мне: = TypeError: следующий() отсутствует 1 требуется позиционная аргумент: «шаг '`:

for char in rev: 
    print(char) 
+1

Вам, кажется, требуется аргумент 'step' в' __next__', но не используется, просто используя 'self.step'. – khelwood

+0

Вы хотите подражать: '' Drapsicle '[:: - 2] '? – jfs

+0

нет, не совсем, спасибо в любом случае – Pawel

ответ

2

Ваш метод __next__ не должен ta ke любые аргументы (кроме self). Вы даже не используете аргумент step, вы (правильно) используете self.step. Просто удалите аргумент:

def __next__(self): 
    if self.index <= 0: 
     raise StopIteration 
    self.index = self.index - self.step 
    return self.data[self.index] 

Дальше у вас возникла ошибка; вы хотите проверить, падает ли индекс ниже 0после вычитания, иначе вы генерируете отрицательные индексы. Вы можете проверить индекс вместе с шагом вычтена:

def __next__(self): 
    next_index = self.index - self.step 
    if next_index < 0: 
     raise StopIteration 
    self.index = next_index 
    return self.data[self.index] 

Демо:

>>> class Reverse: 
...  def __init__(self, data, step): 
...   self.data = data 
...   self.index = len(data) 
...   self.step = step 
...  def __iter__(self): 
...   return self 
...  def __next__(self): 
...   next_index = self.index - self.step 
...   if next_index < 0: 
...    raise StopIteration 
...   self.index = next_index 
...   return self.data[self.index] 
... 

>>> rev = Reverse('Drapsicle', 2) 
>>> for char in rev: 
...  print(char) 
... 
l 
i 
p 
r 
+0

Так просто, спасибо! :) – Pawel

+0

Это возвращает '' e'' до того, как оно закончится; 'self.index = self.index - self.step' должен быть выше' if'. – Cyphase

+0

@Cyphase: хорошо пятнистый; скорректированный ответ для компенсации. –

0

Я понимаю, что это не является прямым ответом на этот вопрос, но в случае, если вы просто хотите, чтобы получить работу , и думаю, что вам нужно реализовать все это самостоятельно; вы этого не делаете.

from itertools import islice 

def reverse_step(iterable, step): 
    # To behave like your code; starts with step-th item 
    start = step - 1 

    for item in islice(reversed(iterable), start, None, step)): 
     yield item 
+0

Я думаю, что OP хочет: 'islice (reverse ('Drapsicle'), None, None, 2)' – jfs

+0

@ J.F.Sebastian, я так не думаю. Вопрос указывает на то, что '' l ''было первым значением, которое получал OP, без каких-либо упоминаний о том, что это неправильно, и OP положительно ответил на ответ Martijn, который возвратил' l, i, p, r'. – Cyphase

0

Для реализации этого:

>>> 'Drapsicle'[::-2] 
'ecsaD' 

как свой собственный итератора:

class Reverse: 
    def __init__(self, data, step): 
     self.data = data 
     self.index = len(data) - 1 
     self.step = step 
    def __iter__(self): 
     return self 
    def __next__(self): 
     if self.index < 0: 
      raise StopIteration 
     value = self.data[self.index] 
     self.index -= self.step 
     return value 

Пример:

>>> list(Reverse('Drapsicle', 2)) 
['e', 'c', 's', 'a', 'D'] 

Примечание:

  • self.index начинается с len - 1
  • __next__() не принимает никаких аргументов, кроме self
  • сначала вы получите value то уменьшаем индекс

Более гибкий дизайн будет отделить реверсивный (например, делегировать до reversed()) и с использованием step != 1 (принять произвольную обратимую итерацию и/или использовать/реализовать расширенную резку), например, на основе @Cyphase's suggestion:

>>> list(islice(reversed('Drapsicle'), None, None, 2)) 
['e', 'c', 's', 'a', 'D'] 
Смежные вопросы