【问题标题】:Can I make a method BE a generator instead of RETURNING one?我可以让一个方法成为一个生成器而不是返回一个吗?
【发布时间】:2019-11-05 00:12:34
【问题描述】:

我希望对象有一个方法,每次调用它时都会从内部列表中返回一个新元素,直到它返回所有元素(但它本身是不可变的)。

虽然我可以存储例如列表中最后一个查看元素的索引,我希望该对象是不可变的,因此该解决方案已解决。 我想在这里使用生成器,但我不知道如何编写它,以便该方法实际上是生成器,而不是返回一个。而且我想从不同的地方访问它,而不是在一个地方的一个循环中,所以我不想每次都使用新的生成器。

我试过了:

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() 本身表现它返回的实际生成器。我希望我在这里有意义:\

【问题讨论】:

    标签: python python-3.x generator python-3.7 yield


    【解决方案1】:

    这看起来有点像 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
      

    【讨论】:

      【解决方案2】:

      函数的每次调用都会返回一个新的生成器,当然。 (该函数仍然是生成器,但它只是在每次调用时重新初始化。)

      如果你真的想共享生成器的状态,你可以像这样拆分一些东西,也许并存储正在进行中的生成器。

      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
      

      【讨论】:

        猜你喜欢
        • 2021-04-09
        • 2014-01-02
        • 2015-04-15
        • 1970-01-01
        • 2017-02-15
        • 1970-01-01
        • 2011-06-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多