如何创建一个自定义的生成器类实现数据生成?

2026-06-11 05:051阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计957个文字,预计阅读时间需要4分钟。

如何创建一个自定义的生成器类实现数据生成?

我看到了很多生成器函数的例子,但我想要了解如何为类编写生成器。以下是一个简化的例子:

pythonclass Fib: def __init__(self): self.a, self.b=0, 1

def __next__(self): self.a, self.b=self.b, self.a + self.b return self.a

我看到很多生成器函数的例子,但我想知道如何为类编写生成器.可以说,我想把斐波纳契系列写成一个类.

class Fib: def __init__(self): self.a, self.b = 0, 1 def __next__(self): yield self.a self.a, self.b = self.b, self.a+self.b f = Fib() for i in range(3): print(next(f))

输出:

<generator object __next__ at 0x000000000A3E4F68> <generator object __next__ at 0x000000000A3E4F68> <generator object __next__ at 0x000000000A3E4F68>

为什么值self.a没有打印?另外,我如何为发电机编写单元测试?

How to write a generator class?

你几乎就在那里,编写一个Iterator类(我在答案的最后显示一个Generator),但每次用next调用对象时都会调用__next__,返回一个生成器对象.相反,使用__iter__:

>>> class Fib: ... def __init__(self): ... self.a, self.b = 0, 1 ... def __iter__(self): ... while True: ... yield self.a ... self.a, self.b = self.b, self.a+self.b ... >>> f = iter(Fib()) >>> for i in range(3): ... print(next(f)) ... 0 1 1

要使类本身成为迭代器:

class Fib: def __init__(self): self.a, self.b = 0, 1 def __next__(self): return_value = self.a self.a, self.b = self.b, self.a+self.b return return_value def __iter__(self): return self

现在:

>>> f = iter(Fib()) >>> for i in range(3): ... print(next(f)) ... 0 1 1

Why is the value self.a not getting printed?

这是您的原始代码和我的评论:

class Fib: def __init__(self): self.a, self.b = 0, 1 def __next__(self): yield self.a # yield makes .__next__() return a generator! self.a, self.b = self.b, self.a+self.b f = Fib() for i in range(3): print(next(f))

因此,每次调用next(f)时,都会得到__next__返回的生成器对象:

如何创建一个自定义的生成器类实现数据生成?

<generator object __next__ at 0x000000000A3E4F68> <generator object __next__ at 0x000000000A3E4F68> <generator object __next__ at 0x000000000A3E4F68>

Also, how do I write unittest for generators?

您仍然需要为Generator实现send和throw方法

from collections import Iterator, Generator import unittest class Test(unittest.TestCase): def test_Fib(self): f = Fib() self.assertEqual(next(f), 0) self.assertEqual(next(f), 1) self.assertEqual(next(f), 1) self.assertEqual(next(f), 2) #etc... def test_Fib_is_iterator(self): f = Fib() self.assertIsInstance(f, Iterator) def test_Fib_is_generator(self): f = Fib() self.assertIsInstance(f, Generator)

现在:

>>> unittest.main(exit=False) ..F ====================================================================== FAIL: test_Fib_is_generator (__main__.Test) ---------------------------------------------------------------------- Traceback (most recent call last): File "<stdin>", line 7, in test_Fib_is_generator AssertionError: <__main__.Fib object at 0x00000000031A6320> is not an instance of <class 'collections.abc.Generator'> ---------------------------------------------------------------------- Ran 3 tests in 0.001s FAILED (failures=1) <unittest.main.TestProgram object at 0x0000000002CAC780>

所以让我们实现一个生成器对象,并利用collections模块中的Generator抽象基类(参见其implementation的源代码),这意味着我们只需要实现send和throw – 给我们close,__ iter __(返回self)和__next__ (与.send(无)相同)免费(见Python data model on coroutines):

class Fib(Generator): def __init__(self): self.a, self.b = 0, 1 def send(self, ignored_arg): return_value = self.a self.a, self.b = self.b, self.a+self.b return return_value def throw(self, type=None, value=None, traceback=None): raise StopIteration

并使用上述相同的测试:

>>> unittest.main(exit=False) ... ---------------------------------------------------------------------- Ran 3 tests in 0.002s OK <unittest.main.TestProgram object at 0x00000000031F7CC0>

Python 2

ABC Generator仅在Python 3中.为了在没有Generator的情况下执行此操作,除了上面定义的方法之外,我们还需要编写至少close,__iter__和__next__.

class Fib(object): def __init__(self): self.a, self.b = 0, 1 def send(self, ignored_arg): return_value = self.a self.a, self.b = self.b, self.a+self.b return return_value def throw(self, type=None, value=None, traceback=None): raise StopIteration def __iter__(self): return self def next(self): return self.send(None) def close(self): """Raise GeneratorExit inside generator. """ try: self.throw(GeneratorExit) except (GeneratorExit, StopIteration): pass else: raise RuntimeError("generator ignored GeneratorExit")

请注意,我直接从Python 3 standard library中复制了一下,没有修改.

本文共计957个文字,预计阅读时间需要4分钟。

如何创建一个自定义的生成器类实现数据生成?

我看到了很多生成器函数的例子,但我想要了解如何为类编写生成器。以下是一个简化的例子:

pythonclass Fib: def __init__(self): self.a, self.b=0, 1

def __next__(self): self.a, self.b=self.b, self.a + self.b return self.a

我看到很多生成器函数的例子,但我想知道如何为类编写生成器.可以说,我想把斐波纳契系列写成一个类.

class Fib: def __init__(self): self.a, self.b = 0, 1 def __next__(self): yield self.a self.a, self.b = self.b, self.a+self.b f = Fib() for i in range(3): print(next(f))

输出:

<generator object __next__ at 0x000000000A3E4F68> <generator object __next__ at 0x000000000A3E4F68> <generator object __next__ at 0x000000000A3E4F68>

为什么值self.a没有打印?另外,我如何为发电机编写单元测试?

How to write a generator class?

你几乎就在那里,编写一个Iterator类(我在答案的最后显示一个Generator),但每次用next调用对象时都会调用__next__,返回一个生成器对象.相反,使用__iter__:

>>> class Fib: ... def __init__(self): ... self.a, self.b = 0, 1 ... def __iter__(self): ... while True: ... yield self.a ... self.a, self.b = self.b, self.a+self.b ... >>> f = iter(Fib()) >>> for i in range(3): ... print(next(f)) ... 0 1 1

要使类本身成为迭代器:

class Fib: def __init__(self): self.a, self.b = 0, 1 def __next__(self): return_value = self.a self.a, self.b = self.b, self.a+self.b return return_value def __iter__(self): return self

现在:

>>> f = iter(Fib()) >>> for i in range(3): ... print(next(f)) ... 0 1 1

Why is the value self.a not getting printed?

这是您的原始代码和我的评论:

class Fib: def __init__(self): self.a, self.b = 0, 1 def __next__(self): yield self.a # yield makes .__next__() return a generator! self.a, self.b = self.b, self.a+self.b f = Fib() for i in range(3): print(next(f))

因此,每次调用next(f)时,都会得到__next__返回的生成器对象:

如何创建一个自定义的生成器类实现数据生成?

<generator object __next__ at 0x000000000A3E4F68> <generator object __next__ at 0x000000000A3E4F68> <generator object __next__ at 0x000000000A3E4F68>

Also, how do I write unittest for generators?

您仍然需要为Generator实现send和throw方法

from collections import Iterator, Generator import unittest class Test(unittest.TestCase): def test_Fib(self): f = Fib() self.assertEqual(next(f), 0) self.assertEqual(next(f), 1) self.assertEqual(next(f), 1) self.assertEqual(next(f), 2) #etc... def test_Fib_is_iterator(self): f = Fib() self.assertIsInstance(f, Iterator) def test_Fib_is_generator(self): f = Fib() self.assertIsInstance(f, Generator)

现在:

>>> unittest.main(exit=False) ..F ====================================================================== FAIL: test_Fib_is_generator (__main__.Test) ---------------------------------------------------------------------- Traceback (most recent call last): File "<stdin>", line 7, in test_Fib_is_generator AssertionError: <__main__.Fib object at 0x00000000031A6320> is not an instance of <class 'collections.abc.Generator'> ---------------------------------------------------------------------- Ran 3 tests in 0.001s FAILED (failures=1) <unittest.main.TestProgram object at 0x0000000002CAC780>

所以让我们实现一个生成器对象,并利用collections模块中的Generator抽象基类(参见其implementation的源代码),这意味着我们只需要实现send和throw – 给我们close,__ iter __(返回self)和__next__ (与.send(无)相同)免费(见Python data model on coroutines):

class Fib(Generator): def __init__(self): self.a, self.b = 0, 1 def send(self, ignored_arg): return_value = self.a self.a, self.b = self.b, self.a+self.b return return_value def throw(self, type=None, value=None, traceback=None): raise StopIteration

并使用上述相同的测试:

>>> unittest.main(exit=False) ... ---------------------------------------------------------------------- Ran 3 tests in 0.002s OK <unittest.main.TestProgram object at 0x00000000031F7CC0>

Python 2

ABC Generator仅在Python 3中.为了在没有Generator的情况下执行此操作,除了上面定义的方法之外,我们还需要编写至少close,__iter__和__next__.

class Fib(object): def __init__(self): self.a, self.b = 0, 1 def send(self, ignored_arg): return_value = self.a self.a, self.b = self.b, self.a+self.b return return_value def throw(self, type=None, value=None, traceback=None): raise StopIteration def __iter__(self): return self def next(self): return self.send(None) def close(self): """Raise GeneratorExit inside generator. """ try: self.throw(GeneratorExit) except (GeneratorExit, StopIteration): pass else: raise RuntimeError("generator ignored GeneratorExit")

请注意,我直接从Python 3 standard library中复制了一下,没有修改.