Могу ли я сделать метод БЫТЬ генератором вместо ВОЗВРАЩАЮЩЕГО? - PullRequest
0 голосов
/ 22 июня 2019

Я хочу иметь объекты, у которых есть метод, который возвращает новый элемент из внутреннего списка каждый раз, когда он вызывается, пока не вернет все их (но сам по себе неизменный).

Хотя я мог бы хранить, например, Индекс последнего просмотренного элемента в списке, я хочу, чтобы объект был неизменным, чтобы решение вышло. Я думал об использовании генератора здесь, но я не знаю, как его написать, чтобы метод на самом деле был генератором, а не возвращал его. И я хочу получить к нему доступ из разных мест, а не в одном цикле в одном месте, поэтому я не хочу каждый раз новый генератор.

Я пробовал это:

class Node:
    def __init__(up, right, down, left):
        self.up = up
        self.right = right
        self.down = down
        self.left = left

    def get_next_neighbour(self):
        for neighbour in [self.up, self.right, self.down, self.left]:
            if neighbour is not None:
                yield neighbour

И я попытался получить к нему доступ так:

n = Node(1, 2, 3, 4)
next_neighbour = next(n.get_next_neighbour()) # returns 1

И затем, в совершенно другой части кода, но с тем же объектом:

next_neighbour = next(n.get_next_neighbour()) # returns 1 again, while I want 2

Я понимаю, что get_next_neighbour() каждый раз возвращает новый генератор, поэтому я всегда получаю 1. Я бы просто хотел, чтобы сам get_next_neighbour() вел себя с фактическим генератором, который он возвращает. Я надеюсь, что здесь есть смысл: \

Ответы [ 2 ]

1 голос
/ 22 июня 2019

Это немного похоже на XY Проблема .

Вместо:

  1. Инициализация:

    n = Node(1, 2, 3, 4)
    
  2. Использование (в разных частях кода):

    next_neighbour = next(n.get_next_neighbour())
    

, вы могли бы сделать:

  1. Инициализация:

    n = Node(1, 2, 3, 4)
    neighbours = n.get_next_neighbour()
    
  2. Использование:

    next_neighbour = next(neighbours)
    

Примечание

  • Я уверен, что это просто опечатка, но вы должны изменить инициализатор на:

    def __init__(self, up, right, down, left):  # self is missing
    
1 голос
/ 22 июня 2019

Каждый вызов функции возвращает новый генератор, конечно.(Функция по-прежнему является генератором, но она просто инициализируется при каждом вызове.)

Если вы действительно хотите поделиться состоянием генератора, вы можете разделить такие вещи, может быть, и сохранить генераторв процессе.

class Node:
    def __init__(self, up, right, down, left):
        self.up = up
        self.right = right
        self.down = down
        self.left = left
        self._neighbor_generator = None

    def _get_next_neighbour(self):
        print('Initialized new generator.')
        for neighbour in [self.up, self.right, self.down, self.left]:
            if neighbour is not None:
                yield neighbour
        self._neighbor_generator = None  # next call will create a new generator

    def get_next_neighbour(self):
        if not self._neighbor_generator:
            self._neighbor_generator = self._get_next_neighbour()
        return self._neighbor_generator

n = Node(1, 2, 3, 4)
for x in range(10):
    print(next(n.get_next_neighbour(), None))

выходы

Initialized new generator.
1
2
3
4
None
Initialized new generator.
1
2
3
4
None
...