Python迭代器和生成器

一、迭代器

1.1、什么是迭代

迭代是指反复的执行一个过程,每次执行都会根据前一次的结果进行调整和优化。在计算机编程中,迭代常常用于循环执行某个操作,直到达到特定的条件或达成目标。迭代也可以用于指代软件开发中的“迭代开发”,即将一个大型软件开发项目分成多个小的迭代周期,每个迭代周期都完成一个可用的软件产品版本,以便及时反馈和调整。迭代的目的是不断优化和改进,逐步达成更好的结果。

1.2、什么是迭代器

迭代器(Iterator)是一种设计模式,它提供了一种访问集合(Collection)中元素的方法,而不必暴露集合内部实现的细节。迭代器为不同类型的集合提供了一种统一的遍历方式,使得集合的迭代访问变得更加简单和方便。迭代器通过提供 hasNext()next() 等方法来实现集合的迭代访问。hasNext() 方法用于判断集合是否还有下一个元素,next() 方法用于返回集合中的下一个元素。迭代器还可以提供 remove() 方法来删除集合中的元素。

1.3、Python 中的可迭代对象

在Python中,可迭代对象是指实现了__iter__()方法的对象,该方法返回一个迭代器(Iterator)对象。以下是一些常见的Python中的可迭代对象:

  • 列表(List):列表是最常用的可迭代对象之一,可以使用for循环遍历列表中的元素。
  • 元组(Tuple):与列表类似,元组也是可迭代对象,可以通过for循环遍历其中的元素。
  • 字符串(String):字符串也是可迭代对象,可以将字符串中的每个字符作为迭代器返回。
  • 集合(Set):集合也是可迭代对象,可以使用for循环遍历集合中的元素。
  • 字典(Dictionary):字典在迭代时默认遍历的是字典的键。可以使用items()方法遍历字典的键值对。
  • 文件对象(File Object):文件对象也是可迭代对象,可以按行迭代读取文件内容。
  • 生成器(Generator):生成器是一种特殊的可迭代对象,可以通过yield语句生成迭代器。

除了以上常见的可迭代对象,还可以自定义类实现__iter__()方法,使其成为可迭代对象。通过实现__iter__()方法,可以定义自己的迭代器行为,从而实现自定义的迭代逻辑。

使用isinstanceIterable判断对象是否可迭代

from collections import Iterable

print isinstance([], Iterable)  # True

print isinstance((), Iterable)  # True

print isinstance("nihao", Iterable)  # True

print isinstance({1, 2, 3}, Iterable)  # True

print isinstance({"name": "liqiang"}, Iterable)  # True

with open("xxx.py", 'r') as f:
    print isinstance(f, Iterable)  # True

n = (x*3 for x in range(4))
print n  # <generator object <genexpr> at 0x106fda410>
print isinstance(n, Iterable)  # True


print isinstance('a', Iterable)  # True

print isinstance(100, Iterable)  # False

1.4、Python 中生成迭代器的方法

1.4.1、iter()函数

该方法返回迭代器对象本身(self)

L = [1, 5, 6]
t = (1, 5, 6)
s = "nihao"
set1 = {1, 5, 6}
d = {"name": "liqiang"}

liter = iter(L)
titer = iter(t)
siter = iter(s)
setiter = iter(set1)
diter = iter(d)

print liter.next() # 1
print titer.next() # 1
print titer.next() # 5
print siter.next() # n
print setiter.next() # 1
print diter.next() # name
print liter.next() # 5
print diter.next()  # 如果没有下一个元素则抛出StopIteration异常
Traceback (most recent call last):
  File "xxx.py", line 44, in <module>
    print diter.next()
StopIteration
1.4.2、enumerate()函数

该函数返回一个迭代器对象,包含传入可迭代对象的索引和元素。enumerate()函数是python的内置函数,用于将一个可遍历的数据对象(如列表、元组、字符串)组合为一个索引序列,同时列出数据和数据下标。它返回一个枚举对象,包含了索引和对应的数据。使用方法如下:

enumerate(iterable, start=0)

其中,iterable是一个可迭代对象,start是可选参数,用于设置起始的索引,默认为0。
示例如下:

name_list = ["zhangsan", "lisi", "wangwu"]
for index, name in enumerate(name_list):
    print(index, name)
print "-----------------------------------"
iter_object = enumerate(name_list)
print iter_object.next()
print iter_object.next()
print iter_object.next()
print iter_object.next()

# 结果如下
(0, 'zhangsan')
(1, 'lisi')
(2, 'wangwu')
-----------------------------------
(0, 'zhangsan')
(1, 'lisi')
(2, 'wangwu')
Traceback (most recent call last):
  File "/Users/gaoyueyun/Documents/code/文件操作/python-test/可迭代对象.py", line 54, in <module>
    print iter_object.next()
StopIteration
1.4.3、zip()函数

zip()函数是python的内置函数,用于将多个可迭代对象合并成一个元组序列,常用于将多个列表、元组或其他可迭代对象中的对应元素进行配对。使用方法如下:

zip(*iterables)

*iterables表示一个或多个可迭代对象,可以是列表、元组、字符串、集合等。zip()函数将这些可迭代对象中的对应元素组合成为一个元组序列,返回一个zip对象,可以通过iter()函数将其转换为迭代器。

names_list = ["zhangsan", "lisi", "wangwu"]
ages_list = [20, 25, 30]
heights_list = [1.6, 1.8, 1.7]

for name, age, height in zip(names_list, ages_list, heights_list):
    print(name, age, height)
print "-----------------------------------"
iter_object = zip(names_list, ages_list, heights_list)
print iter_object.next()
print "-----------------------------------"
iter_object = iter(zip(names_list, ages_list, heights_list))
print iter_object.next()
print iter_object.next()
print iter_object.next()

# 结果如下
('zhangsan', 20, 1.6)
('lisi', 25, 1.8)
('wangwu', 30, 1.7)
-----------------------------------
Traceback (most recent call last):
  File "/Users/gaoyueyun/Documents/code/文件操作/python-test/可迭代对象.py", line 54, in <module>
    print iter_object.next()
AttributeError: 'list' object has no attribute 'next'
-----------------------------------
('zhangsan', 20, 1.6)
('lisi', 25, 1.8)
('wangwu', 30, 1.7)
1.4.4、map()函数

map()函数是python的内置函数,用于对一个或多个可迭代对象中的元素逐个应用某个函数,返回一个迭代器。使用方法如下:

map(function, *iterables)

function是一个函数对象,*iterables表示一个或多个可迭代对象,可以是列表、元组、字符串、集合等。map()函数将function应用于iterables中的元素,逐个返回结果。示例如下:

def square(x):
    return x ** 2


numbers = [1, 2, 3, 4, 5]
squared_numbers = map(square, numbers)

print(squared_numbers)
print "----------------------------------"
squared_numbers = iter(map(square, numbers))
print squared_numbers.next()
print squared_numbers.next()
print squared_numbers.next()
print squared_numbers.next()

# 结果如下
[1, 4, 9, 16, 25]
----------------------------------
1
4
9
16
1.4.5、filter()函数

filter()函数是python的内置函数,用于过滤一个可迭代对象中的元素,返回一个迭代器。使用方法如下:

filter(function, iterable)

function是一个用于过滤元素的函数对象,iterable是一个可迭代对象,可以是列表、元组、字符串、集合等。filter()函数将function应用于iterable中的每个元素,返回一个只包含满足条件的元素的迭代器。示例如下:

num_list = [1, 2, 3, 4, 5]
filter_object = iter(filter(lambda x: x > 2, num_list))
print filter_object.next()
print filter_object.next()
print filter_object.next()


def get_num(x):
    if x > 2:
        return x


filter_object = filter(get_num, num_list)
print filter_object
filter_object = iter(filter(get_num, num_list))
print filter_object.next()
print filter_object.next()
print filter_object.next()

# 结果如下
3
4
5
[3, 4, 5]
3
4
5
1.4.6、reversed()函数

reversed()函数是python的内置函数,用于反转一个序列(如列表、元组、字符串)的元素顺序,返回一个迭代器。使用方法如下:

reversed(sequence)

sequence是一个序列,可以是列表、元组、字符串等。reversed()函数将sequence中的元素顺序进行反转,返回一个迭代器。示例如下:

num_list = [1, 2, 3, 4, 5]
re_object = reversed(num_list)
print re_object.next()
print re_object.next()
print re_object.next()
print re_object.next()
print re_object.next()

# 结果如下
5
4
3
2
1
1.4.7、sorted()函数

sorted()函数是python的内置函数,用于对一个序列(如列表、元组、字符串)进行排序,返回一个新的已排序的列表。使用方法如下:

sorted(iterable, key=None, reverse=False)

iterable是一个序列,可以是列表、元组、字符串等;key是一个函数,用于指定排序规则,默认为None,表示按照元素的大小比较进行排序;reverse是一个布尔值,用于指定是否降序排列,默认为False,表示升序排列。示例如下:

num_list = [6, 0, 7, 3, 9, 12]
s_object = sorted(num_list)
print s_object
print "------------------------------"
s2_object = iter(sorted(num_list, reverse=True))
print s2_object
print s2_object.next()
print s2_object.next()
print s2_object.next()
print s2_object.next()
print s2_object.next()
print s2_object.next()

# 结果如下
[0, 3, 6, 7, 9, 12]
------------------------------
<listiterator object at 0x106a6e150>
12
9
7
6
3
0

1.5、自定义迭代器类

自定义迭代器类需要实现__iter__()__next__()两个方法。iter()方法返回迭代器本身,next()方法用于返回容器中的下一个值。例如:

class MyIterator:
    def __init__(self, container):
        self.container = container
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.index >= len(self.container):
            raise StopIteration
        value = self.container[self.index]
        self.index += 1
        return value


iter01 = MyIterator([1, 2, 3])
print iter01.__next__()
print iter01.__next__()
print iter01.__next__()

# 结果如下:
1
2
3

1.6、迭代器和列表的区别

  • 存储方式:列表是一种数据结构,以连续的内存空间来存储元素,可以随机访问其中的任意元素。而迭代器是一种访问集合中元素的方式,可以一次访问一个元素,而不需要提前加载所有元素到内存中。

  • 内存占用:列表将所有元素一次性加载到内存中,占用的内存空间较大。而迭代器仅在需要时生成和返回元素,占用的内存空间较小。

  • 访问方式:列表可以通过索引来直接访问和修改元素。而迭代器需要逐个调用next()方法来访问和返回元素。

  • 遍历次数:列表可以被多次遍历,每次遍历都是从头开始。而迭代器只能遍历一次,遍历结束后需要重新创建迭代器对象才能再次遍历。

  • 惰性计算:迭代器可以进行惰性计算,即在需要时才生成下一个元素,可以节省计算资源。而列表在创建时就会立即计算和存储所有元素。

迭代器是一种按需生成和访问元素的方式,适用于处理大量数据或无需提前加载所有数据的场景。列表是一种数据结构,适用于需要随机访问元素或多次遍历的场景。

迭代器(Iterator)和可迭代对象(Iterable)区别

  • 接口实现:可迭代对象是指实现了__iter__()方法的对象,该方法返回一个迭代器对象。而迭代器是指实现了__iter__()__next__()方法的对象,其中__iter__()方法返回迭代器对象本身,next()方法用于返回容器中的下一个值。

  • 访问方式:可迭代对象可以通过for循环直接进行遍历,也可以通过iter()函数将其转换为迭代器。迭代器需要使用next()函数或者for循环来逐个访问元素。

  • 存储方式:可迭代对象可以是一次性将所有元素存储在内存中的数据结构,例如列表、元组、集合等。迭代器是一种按需生成和返回元素的机制,可以节省内存空间,特别适用于处理大量数据或无需提前加载所有数据的情况。

  • 遍历次数:可迭代对象可以被多次遍历,每次遍历都是从头开始。而迭代器只能遍历一次,遍历结束后需要重新创建迭代器对象才能再次遍历。

  • 惰性计算:迭代器可以进行惰性计算,即在需要时才生成下一个元素,可以节省计算资源。可迭代对象在创建时就会立即计算和存储所有元素。

可迭代对象是一种具有遍历能力的对象,它可以通过迭代器来进行遍历。迭代器是一种按需生成和访问元素的机制,用于遍历可迭代对象。迭代器相对于可迭代对象更加灵活和节省内存,适用于处理大量数据或需要惰性计算的场景。因此,在Python中使用迭代器可以提高程序的效率和性能。

1.7、迭代器和for循环区别

  • 实现方式:迭代器是基于迭代器协议实现的,需要自定义__iter__()__next__()方法。而for循环是Python提供的一种高级语法,用于遍历可迭代对象。

  • 访问方式:使用迭代器时,需要通过调用next()函数或者使用for循环来逐个访问元素。而for循环直接使用可迭代对象进行遍历,无需关心迭代器的具体实现。

  • 遍历方式:迭代器逐个返回元素,可以按需生成和返回元素,即使处理大量数据也不需要提前加载所有数据到内存中。而for循环会一次性将所有元素加载到内存中,然后按顺序进行遍历。

  • 遍历次数:迭代器只能遍历一次,遍历结束后需要重新创建迭代器对象才能再次遍历。而for循环可以多次遍历可迭代对象,每次都是从头开始遍历。

  • 使用场景:迭代器适用于处理大量数据或无需提前加载所有数据的情况,可以节省内存空间。for循环适用于一次性遍历所有元素,并且无需关心具体的迭代实现。

迭代器是一种按需生成和访问元素的机制,适用于处理大量数据或需要惰性计算的场景。而for循环是一种便捷的语法,适用于遍历可迭代对象,无需关心其具体的迭代实现。

二、生成器

2.1、什么是生成器

在 Python 中,使用了yield的函数被称为生成器(generator)。yield是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。当在生成器函数中使用yield语句时,函数的执行将会暂停,并将yield后面的表达式作为当前迭代的值返回。然后,每次调用生成器的next()方法或使用for循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到yield语句。这样,生成器函数可以逐步产生值,而不需要一次性计算并返回所有结果。调用一个生成器函数,返回的是一个迭代器对象。

2.2、创建生成器

2.2.1、生成器表达式

生成器表达式是一种类似于列表推导式的语法,但是生成的是一个生成器对象。使用生成器表达式时,不需要显式定义函数,直接在一对圆括号内编写表达式即可。示例如下:

gen = (x for x in range(0, 4))
print gen.next()
print(next(gen))
print(next(gen))
print gen.next()

print "-------------------------"

list_method = [x for x in range(0, 4)]
print next(list_method)
print list_method.next()

# 结果如下
0
1
2
3
-------------------------
Traceback (most recent call last):
  File "/Users/gaoyueyun/Documents/code/文件操作/python-test/可迭代对象.py", line 151, in <module>
    print next(list_method)
TypeError: list object is not an iterator
2.2.2、生成器函数

生成器函数是一种特殊的函数,其中包含yield语句。当调用生成器函数时,并不会执行函数体内的代码,而是返回一个生成器对象。每次调用生成器的__next__()方法时,会执行生成器函数体内的代码,直到遇到yield语句,将yield后面的表达式作为生成器的返回值,并暂停执行函数。下次调用__next__()方法时,会从上次暂停的位置继续执行。示例如下:

def countdown(n):
    while n > 0:
        yield n
        n -= 1


# 创建生成器对象
generator = countdown(5)

# 通过迭代生成器获取值
print(next(generator))  # 输出: 5
print(next(generator))  # 输出: 4
print(next(generator))  # 输出: 3

# 使用 for 循环迭代生成器
for value in generator:
    print(value)  # 输出: 2 1

2.3、生成器常用方法

2.3.1、send(value)

向生成器发送一个值,并继续生成器的执行。该方法的作用类似于yield表达式,可以将一个值发送给生成器,并让生成器继续执行。使用该方法时,需要先调用一次next()方法,使生成器运行到yield语句的位置。示例如下:

def my_generator():
    while True:
        value = yield
        print(value)

gen = my_generator()
next(gen)  # 运行到 yield 语句
gen.send(1)  # 输出:1
gen.send(2)  # 输出:2

使用send(value)方法时,需要注意以下几点:

  • 在第一次调用生成器对象之前,需要先使用一次next()方法,使生成器执行到yield语句的位置。

  • 生成器对象的send(value)方法会将value赋值给yield表达式左边的变量,并继续执行生成器,直到遇到下一个yield表达式或结束。

  • 首次调用send(value)方法时,传递的参数值会被忽略,即不会赋值给第一个yield表达式的左边变量。如果非要给第一个yield表达式传递一个初始值,可以通过先调用next()方法,然后使用send(value)方法。

在上述示例中,首先调用next(gen)将生成器执行到第一个yield语句的位置。然后,gen.send(1)将值1发送给生成器,赋值给yield表达式左边的变量value,并继续执行生成器,打印出1。接着,gen.send(2)再次发送值2给生成器,赋值给value并打印出2。

通过使用send(value)方法,我们可以在生成器的执行过程中提供不同的输入值,并根据需要进行后续的处理。

2.3.2、close()

关闭生成器。调用该方法后,生成器将无法再次使用。

def countdown(n):
    while n > 0:
        yield n
        n -= 1


# 创建生成器对象
generator = countdown(5)

# 通过迭代生成器获取值
print(next(generator))  # 输出: 5
generator.close()       # 关闭生成器
print(next(generator))  # 抛出StopIteration异常
2.3.3、throw()

向生成器抛出一个异常。使用该方法时,需要先调用一次next()方法,使生成器运行到yield语句的位置。示例如下:

def countdown(n):
    while n > 0:
        try:
            yield n
            n -= 1
        except ValueError:
            print "报错了"


# 创建生成器对象
generator = countdown(5)

# 通过迭代生成器获取值
print(next(generator))       # 输出: 5
print(next(generator))       # 输出: 4
generator.throw(ValueError)  # 输出: 报错了
print(next(generator))       # 输出: 3
print(next(generator))       # 输出: 2
print(next(generator))       # 输出: 1
2.3.3、yield from

将一个可迭代对象委托给生成器。使用该语法可以简化生成器的实现,使其更加清晰和易读。需要说明的是,python2不支持,python3.3以后支持。示例如下:

def countdown(n):
    while n > 0:
        yield n
        n -= 1

def my_gen(n):
    yield from countdown(n)
    yield n+1



# 创建生成器对象
generator = my_gen(5)

print(generator)
print(list(generator)) # [5, 4, 3, 2, 1, 6]

# 通过迭代生成器获取值
print(next(generator))

<generator object my_gen at 0x10856f270>
[5, 4, 3, 2, 1, 6]
Traceback (most recent call last):
  File "xxx.py", line 167, in <module>
    print(next(generator))
StopIteration

2.4、yieldyield from 区别

yield原理:

  • yield用于定义生成器函数(包含yield语句的函数)。
  • 当生成器函数被调用时,它会返回一个生成器对象,而不是立即执行函数体。
  • 在生成器函数中,yield语句将生成一个值,并将生成器的状态暂停,保存当前的上下文环境,并返回值给调用者。
  • 调用生成器的__next__()方法或使用for循环迭代生成器时,会恢复生成器的状态,继续执行后续的代码。
  • yield语句可以出现在函数中的任意位置,并且可以出现多次。

yield from原理:

  • yield from语句用于在生成器函数内部的控制权委派另一个生成器或可迭代对象进行迭代。
  • 当使用yield from委派给子生成器时,子生成器将负责产生值,并将这些值返回给yield from的调用者。同时,yield from还可以传递给子生成器发送的值。
  • yield from会自动处理委派生成器和子生成器之间的异常传递,使得异常能够正确地向上层传递。
  • yield from可以用于多层嵌套,将委派生成器和子生成器层层连接起来。

yield是一个表达式,它可以将值传递给调用方并暂停函数的执行。当再次调用函数时,函数会从暂停的位置继续执行,直到遇到下一个yieldyield实际上是生成器函数的核心机制,它允许生成器函数产生多个值,并且在每次产生值后可以暂停执行。

yield from是Python3.3中引入的新特性,它可以将另一个生成器或可迭代对象委托给当前生成器来生成。使用yield from委托生成器时,有两种情况:

  • 如果委托的是生成器,那么委托生成器会完全接管当前生成器的控制权,直到委托生成器返回或抛出异常。

  • 如果委托的是可迭代对象,那么yield from会自动处理迭代器和异常,直到可迭代对象耗尽或抛出异常。yield from语句将返回可迭代对象生成的所有值。

从原理上来说,yield from的实现比yield复杂得多。yield from实际上是一个语法糖,它隐藏了生成器和迭代器之间的所有细节。当使用yield from语句时,Python会自动处理所有的迭代器和生成器协议。具体来说,Python会自动创建一个子生成器对象,并在子生成器完成时自动捕获并处理所有的StopIteration异常。

举个例子,考虑以下代码:

list01 = [0, 1, 2, 3, 4]


def g1():
    yield list01


def g2():
    yield from list01


it1 = g1()
it2 = g2()

for x in it1:
    print(x)

for x in it2:
    print(x)

# 结果如下
[0, 1, 2, 3, 4]
0
1
2
3
4

yield from相比yield优势

  • yield from语句可以将嵌套的可迭代对象“展开”,使得代码更简洁,而不需要显式地写出循环语句。
  • yield from语句可以简化异常处理,当嵌套的可迭代对象中发生异常时,它会自动传播到生成器中,并被捕获和处理。
  • yield from语句可以将生成器的控制权交给其他生成器或协程,以实现更灵活的协作式并发编程。
  • yield from语句在处理过程中会自动处理子生成器返回的值和异常,而yield语句需要手动处理。

2.5、迭代器和生成器的异同

共同点

  • 迭代器和生成器都是用于实现迭代行为的工具,用于遍历序列中的元素或处理大量数据。
  • 迭代器和生成器都是惰性计算的,即只在需要时才产生值。
  • 迭代器和生成器都可以实现无限序列的处理,因为它们是按需生成值的。

区别

  • 迭代器是任何实现了__iter__()__next__()方法的对象,它是一个迭代器协议的实现。而生成器是一种特殊的迭代器,它是通过生成器函数或生成器表达式创建的。
  • 生成器是一种更加高级、更加方便的实现迭代行为的方式,它使用yield关键字逐步产生值,并在每次产生值后暂停执行,等待下一次迭代。迭代器则需要显式地实现__next__()方法来产生值。
  • 生成器可以通过生成器函数或生成器表达式来创建,而迭代器则可以是任何实现了__iter__()__next__()方法的对象,例如列表、元组、字符串等。

2.6、语法糖

语法糖(Syntactic sugar)是指编程语言中的一种语法构造,它可以使代码更简洁、易读和易写,但实际上并没有提供任何新的功能。语法糖是对底层语言特性的高级封装,使得编码变得更加方便和直观。

语法糖通常是一种编译器或解释器的功能,它可以将简洁的高级语法转换为底层的更复杂的语法结构。 这样做的目的是为了提高代码的可读性和可维护性,以及减少程序员编写错误的可能性。

语法糖可以包括各种形式的简化语法,如简洁的表达式、简化的控制结构或简化的数据类型定义。它们通常不是必需的,可以通过使用底层语言特性来实现相同的功能,但语法糖可以大大简化代码的编写和理解。

常见的语法糖包括:简化的迭代器和循环结构、自动类型推导、操作符重载、匿名函数和Lambda表达式等。这些语法糖使得代码更加简洁、易读和易写,但实际上它们都是通过编译器或解释器在底层进行转换和处理的。

python 常见语法糖

  • 列表推导式:用一行代码快速生成列表,例如 [x for x in range(10)] 可以生成一个包含0到9的列表。

  • 字典推导式:类似于列表推导式,用一行代码快速生成字典,例如 {x: x**2 for x in range(10)} 可以生成一个键为0到9的数字,对应值为它们的平方的字典。

  • 带有if条件的推导式:在列表推导式或字典推导式中加入if条件,可以根据条件过滤元素或进行条件赋值。例如 [x for x in range(10) if x % 2 == 0] 可以生成一个包含0到9中偶数的列表。

  • 装饰器:装饰器是一种用于修改或增强函数功能的语法糖。通过在函数定义前使用@符号和装饰器函数,可以简化函数的装饰过程。

  • 上下文管理器:通过with语句和__enter____exit__方法,可以简化对资源的管理,例如文件的打开和关闭。

2.7、yield 实现斐波那契数列

斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。
在这里插入图片描述

指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)

def fibonacci(n):
    """斐波那契数列实现"""
    a, b = 0, 1
    while n > 0:
        a, b = b, a + b
        n -= 1
        yield a


# 另一种写法
def fibonacci(n): # 生成器函数 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n): 
            return
        yield a
        a, b = b, a + b
        counter += 1

# 获取斐波那契数列前 10 个成员
fibonacci_ = fibonacci(10)
for i in fibonacci_:
    print(i)

# 结果如下
1
1
2
3
5
8
13
21
34
55

三、参考文档

1、https://www.yisu.com/zixun/312592.html

2、https://blog.csdn.net/qq_36441027/article/details/105919241

3、https://www.cnblogs.com/chengxuyuanaa/p/13065794.html

4、https://www.cnblogs.com/jiba/p/14047159.html

5、https://my.oschina.net/u/4330317/blog/4202095

6、https://www.cnblogs.com/alex3714/articles/5765046.html

7、https://kelepython.readthedocs.io/zh/latest/c01/c01_11.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值