2

I have a pdf in which I create page numbers for a table of content. Some topics in a pdf overlaps into multiple pages for that I need to use steps while others stay on one page.

I have created a custom iterator like this:

class IndexPageCounter:
    """
        Used to create index page counter for a table of content
    """

    def __iter__(self):
        self.num = 1
        return self

    def __next__(self, step=1):
        num = self.num
        self.num += step
        return num

and call it like this:

obj = iter(IndexPageCounter())
print(next(obj)) # this works fine
print(next(obj, step=2) # this doesn't work
# above line gives TypeError: next() takes no keyword arguments

I tried looking it up but I don't see any example of creating a custom iterator with step.

Edit:

I can't pass the value of step in the constructor as the value of the step is not constant.

5
  • next doesn't take any kwargs. Pass the step as a constructor argument (similar to how range works), or use a different method. Commented Feb 15, 2022 at 5:13
  • @SuperStormer Why is it downvoted ? The value of step is not constant I can't pass it in constructor Commented Feb 15, 2022 at 5:16
  • then it's not suited for the iterator protocol - just use a custom method instead. Commented Feb 15, 2022 at 5:18
  • 1
    @SuperStormer I don't see a reason of downvoting this question Commented Feb 15, 2022 at 5:23
  • @hilberts_drinking_problem I fixed it by creating a separate function in the class check my answer thanks. Commented Feb 15, 2022 at 6:51

2 Answers 2

1

As mentioned in a comment, the built in next() fn doesn’t have a steps kwarg. I think you can approach this problem with a generator instead though. Something like:

def next_index_page(step=1):
  last_page = 25
  index = 1 # first page is 1 
  while index <= last_page:
    yield index 
    index += step

If you need this to be a custom iterator class, consider putting the logic for calculating step into __next__ so that you don’t need to specify step from the calling code.

Something like

class IndexIter:
  def __init__(self, start_page=1):
    self.current_index = start_page

  def __iter__(self):
    return self

  def __next__(self):
    self.current_index = self.get_next_index_page()
    return current_index

  def get_next_index_page(self):
    # logic for getting next index

Note: I would strongly suggest designing your code so that the logic for something like get_next_index_page() is in the generator or the custom iterator's __next__() method. This is because you want your iterator to behave like an iterator (i.e. you can call next() or loop through it). If you don't have this your example would be better served with a simple variable that you increment.

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

1 Comment

Thanks a lot, I have fixed it by creating a separate function, check my answer.
0

I fixed it by creating a separate function get_next like this:

class IndexPageCounter:
    """
        Used to create index page counter for a table of content
    """

    def __iter__(self):
        self.num = 1
        return self

    def __next__(self):
        num = self.num
        self.num += 1
        return num

    def get_next(self, step=1):
       for _ in range(0, step):
          self.__next__()
       return self.num

and call it like this:

obj = iter(IndexPageCounter())
print(obj.get_next()) # works
print(obj.get_next(step=2)) # works too

1 Comment

If I was reviewing this code I'd suggest not using an iter at all if you're just going to add a get_next method. In this example you essentially have a class wrapping an integer variable.

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.