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 Iterableprint isinstance([], Iterable)  # Trueprint isinstance((), Iterable)  # Trueprint isinstance("nihao", Iterable)  # Trueprint isinstance({1, 2, 3}, Iterable)  # Trueprint isinstance({"name": "liqiang"}, Iterable)  # Truewith open("xxx.py", 'r') as f:print isinstance(f, Iterable)  # Truen = (x*3 for x in range(4))
print n  # <generator object <genexpr> at 0x106fda410>
print isinstance(n, Iterable)  # Trueprint isinstance('a', Iterable)  # Trueprint 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 ** 2numbers = [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 xfilter_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 = containerself.index = 0def __iter__(self):return selfdef __next__(self):if self.index >= len(self.container):raise StopIterationvalue = self.container[self.index]self.index += 1return valueiter01 = 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 nn -= 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 = yieldprint(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 nn -= 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 nn -= 1except 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 nn -= 1def 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 list01def g2():yield from list01it1 = 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, 1while n > 0:a, b = b, a + bn -= 1yield a# 另一种写法
def fibonacci(n): # 生成器函数 - 斐波那契a, b, counter = 0, 1, 0while True:if (counter > n): returnyield aa, b = b, a + bcounter += 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/54567.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R语言主成分分析

R语言主成分分析 之前介绍过怎么用SPSS进行主成分分析(PCA)&#xff0c;已经忘了的朋友们可以到主页看看 今天主要介绍下R语言主成分分析的几种方法。都是入门级别&#xff0c;跟着我一步步走&#xff0c;一点都不难哈~ 首先调用R语言自带的数据集&#xff0c;USArrests。这…

【Go 基础篇】Go语言中的数组:初识与应用

Go语言以其简洁、高效和强大的特性在编程界广受欢迎。数组作为一种基本的数据结构&#xff0c;在各种应用场景中扮演着重要角色。本文将引入Go语言中的数组&#xff0c;介绍其特点、创建、初始化以及基本应用&#xff0c;为你打开数组的大门。 前言 数组是一种固定大小的数据…

七层、四层和五层网络模型区别和联系

七层、四层和五层网络模型区别和联系 概述OSI网络7层模型&#xff08;概念型框架&#xff09;概述图片分析 四层模型概述常用协议OSI与TCP/IP四层的区别 五层模型概述三种网络模型对比 总结 概述 网络模型-七层模型&#xff08;OSI模型&#xff09;、五层协议体系结构和TCP/IP…

性能优化之分库分表

1、什么是分库分表 1.1、分表 将同一个库中的一张表&#xff08;比如SPU表&#xff09;按某种方式&#xff08;垂直拆分、水平拆分&#xff09;拆分成SPU1、SPU2、SPU3、SPU4…等若干张表&#xff0c;如下图所示&#xff1a; 1.2、分库 在表数据不变的情况下&#xff0c;对…

“R语言+遥感“水环境综合评价方法

详情点击链接&#xff1a;"R语言遥感"水环境综合评价方法 一&#xff1a;R语言 1.1 R语言特点&#xff08;R语言&#xff09; 1.2 安装R&#xff08;R语言&#xff09; 1.3 安装RStudio&#xff08;R语言&#xff09; &#xff08;1&#xff09;下载地址 &…

如何基于亚马逊云科技打造高性能的 SQL 向量数据库 MyScale

MyScale 是一款完全托管于亚马逊云科技、支持 SQL 的高效向量数据库。MyScale 的优势在于&#xff0c;它在提供与专用向量数据库相匹敌甚至优于的性能的同时&#xff0c;还支持完整的 SQL 语法。在这篇文章中&#xff0c;我们将阐述 MyScale 是如何借助亚马逊云科技的基础设施&…

pnpm无法加载文件 (解决方法 )

现在要运行一个TS的项目&#xff0c;我的电脑上没有安装pnpm&#xff0c;导致我的vscode一直报错无法加载。 pnpm安装&#xff1a; npm install -g pnpm pnpm : 无法加载文件 pnpm : 无法加载文件 C:\Users\HP\AppData\Roaming\npm\pnpm.ps1&#xff0c;因为在此系统上禁止运…

英语略读三

课文的客观&#xff0c;或者逻辑推理 同增通减 比错 对比选项&#xff0c;找一个明显的区别 防并列&#xff0c;文章再说主语在干嘛干嘛的&#xff0c;但是与答案的角度不一样&#xff0c;是并列的关系 在对比选项&#xff0c;不是证明正确的 具体问题具体分析&#xff0c;but…

【30天熟悉Go语言】10 Go异常处理机制

作者&#xff1a;秃秃爱健身&#xff0c;多平台博客专家&#xff0c;某大厂后端开发&#xff0c;个人IP起于源码分析文章 &#x1f60b;。 源码系列专栏&#xff1a;Spring MVC源码系列、Spring Boot源码系列、SpringCloud源码系列&#xff08;含&#xff1a;Ribbon、Feign&…

[Linux]文件IO

文章目录 1. 文件描述符1.1 虚拟地址空间1.1.1 存在的意义1.1.2 分区 1.2 文件描述符1.2.1 文件描述符1.2.2 文件描述符表 2. Linux系统文件IO2.1 open/close2.1.1 函数原型2.1.2 close函数原型2.1.3 打开已存在文件2.1.4 创建新文件2.1.5 文件状态判断 2.2 read/write2.2.1 re…

Spring Boot(Vue3+ElementPlus+Axios+MyBatisPlus+Spring Boot 前后端分离)【四】

&#x1f600;前言 本篇博文是关于Spring Boot(Vue3ElementPlusAxiosMyBatisPlusSpring Boot 前后端分离)【四】&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章…

VMware虚拟机连不上网络

固定ip地址 进入网络配置文件 cd /etc/sysconfig/network-scripts 打开文件 vi ifcfg-ens33 编辑 BOOTPROTO设置为static&#xff0c;有3个值&#xff08;decp、none、static&#xff09; BOOTPROTO"static" 打开网络 ONBOOT"yes" 固定ip IPADDR1…

为什么需要websocket?

一、为什么需要websocket&#xff1f; 前端和后端的交互模式最常见的就是前端发数据请求&#xff0c;从后端拿到数据后展示到页面中。如果前端不做操作&#xff0c;后端不能主动向前端推送数据&#xff0c;这也是http协议的缺陷。 因此&#xff0c;一种新的通信协议应运而生---…

【滑动窗口】leetcode1004:最大连续1的个数

一.题目描述 最大连续1的个数 这道题要我们找最大连续1的个数&#xff0c;看到“连续”二字&#xff0c;我们要想到滑动窗口的方法。滑动窗口的研究对象是一个连续的区间&#xff0c;这个区间需要满足某个条件。那么本题要找的是怎样的区间呢&#xff1f;是一个通过翻转0后得到…

抖音web主页视频爬虫

需要抖音主页视频爬虫源码的发私信&#xff0c;小偿即可获得长期有效的采集程序。 比构造 s_v_web_id 验证滑块的方法更快&#xff0c;更稳定。

JVM理论知识

一、JVM内存结构 java的内存模型主要分为5个部分&#xff0c;分别是&#xff1a;JVM堆、JVM栈、本地栈、方法区还有程序计数器&#xff0c;他们的用途分别是&#xff1a; JVM堆&#xff1a;新建的对象都会放在这里&#xff0c;他是JVM中所占内存最大的区域。他又分为新生区还…

2022年09月 C/C++(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;最长上升子序列 一个数的序列bi&#xff0c;当b1 < b2 < … < bS的时候&#xff0c;我们称这个序列是上升的。对于给定的一个序列(a1, a2, …, aN)&#xff0c;我们可以得到一些上升的子序列(ai1, ai2, …, aiK)&#xff0c;这里1 < i1 < i2 &…

【中危】Apache Ivy<2.5.2 存在XXE漏洞 (CVE-2022-46751)

漏洞描述 Apache Ivy 是一个管理基于 ANT 项目依赖关系的开源工具&#xff0c;文档类型定义(DTD)是一种文档类型定义语言,它用于定义XML文档中所包含的元素以及元素之间的关系。 Apache Ivy 2.5.2之前版本中&#xff0c;当解析自身配置、Ivy 文件或 Apache Maven 的 POM 文件…

设计模式--适配器模式(Adapter Pattern)

一、什么是适配器模式&#xff08;Adapter Pattern&#xff09; 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许将一个类的接口转换成客户端所期望的另一个接口。适配器模式主要用于解决不兼容接口之间的问题&#xff0c;使得原本…

leetcode:338. 比特位计数(python3解法)

难度&#xff1a;简单 给你一个整数 n &#xff0c;对于 0 < i < n 中的每个 i &#xff0c;计算其二进制表示中 1 的个数 &#xff0c;返回一个长度为 n 1 的数组 ans 作为答案。 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;[0,1,1] 解释&#xff1a; 0…