python迭代器与生成器
1.迭代器
在Python中,迭代器(Iterator)是一种对象,它表示一个数据流,允许你一次访问一个元素,直到数据流结束。迭代器对象实现了两个特殊方法:__iter__()
和 __next__()
。
__iter__()
方法:返回迭代器对象本身。这通常用于使对象既是可迭代的(iterable),又是迭代器。__next__()
方法:返回序列中的下一个元素。如果已经到达序列的末尾,则引发StopIteration
异常,以通知迭代终止。
1.1创建自定义迭代器
你可以通过定义一个类并实现这两个方法来创建自己的迭代器。以下是一个简单的例子:
class MyRange: def __init__(self, start, end): self.current = start self.end = end def __iter__(self): return self def __next__(self): if self.current < self.end: num = self.current self.current += 1 return num else: raise StopIteration # 使用自定义迭代器 my_range = MyRange(1, 5) for num in my_range: print(num)
1.2使用内置函数创建迭代器
Python提供了许多内置函数和类型,它们返回迭代器对象。例如:
range(start, stop, step)
:生成一个整数序列。map(function, iterable)
:对可迭代对象中的每个元素应用一个函数。filter(function, iterable)
:过滤可迭代对象中的元素,只保留使函数返回True的元素。zip(*iterables)
:将多个可迭代对象打包成一个元组的迭代器。
# 使用 range for i in range(3, 10, 2): print(i) # 使用 map numbers = [1, 2, 3, 4, 5] squared = map(lambda x: x ** 2, numbers) for sq in squared: print(sq) # 使用 filter even_numbers = filter(lambda x: x % 2 == 0, numbers) for even in even_numbers: print(even) # 使用 zip names = ['Alice', 'Bob', 'Charlie'] scores = [85, 90, 78] for name, score in zip(names, scores): print(f'{name}: {score}')
1.3迭代器的优点
- 节省内存:迭代器一次只返回一个元素,这对于处理大数据集非常有用。
- 惰性求值:迭代器在需要时才生成值,这可以提高性能。
- 灵活性:你可以自定义迭代逻辑,以满足特定需求。
1.4转换为迭代器
任何实现了 __iter__()
方法的对象都是可迭代的(iterable)。你可以使用内置的 iter()
函数将可迭代对象转换为迭代器。
iterable = [1, 2, 3] iterator = iter(iterable) print(next(iterator)) # 输出: 1 print(next(iterator)) # 输出: 2 print(next(iterator)) # 输出: 3 # print(next(iterator)) # 引发 StopIteration 异常
2.python生成器
在Python中,生成器(Generator)是一种特殊的迭代器,它使用函数来产生序列中的元素。与普通的函数不同,生成器函数使用yield
关键字来暂停函数执行并产生一个值,然后在需要下一个值时再次恢复执行。这种机制允许你按需生成值,而不必一次性将所有值加载到内存中,这对于处理大量数据或无限序列特别有用。
2.1创建生成器
要创建一个生成器,你只需定义一个函数,并在函数中使用yield
关键字。每次调用next()
方法(或在循环中迭代生成器时)时,函数将从上次yield
的位置继续执行,直到遇到下一个yield
或函数结束。
下面是一个简单的生成器函数示例:
def simple_generator(): yield 1 yield 2 yield 3 # 使用生成器 gen = simple_generator() print(next(gen)) # 输出: 1 print(next(gen)) # 输出: 2 print(next(gen)) # 输出: 3 # print(next(gen)) # 引发 StopIteration 异常
2.2生成器表达式
除了使用函数定义生成器外,Python还提供了生成器表达式,它们类似于列表推导式,但使用圆括号()
而不是方括号[]
。生成器表达式返回一个生成器对象,而不是一次性生成整个列表。
# 列表推导式 squares = [x**2 for x in range(5)] print(squares) # 输出: [0, 1, 4, 9, 16] # 生成器表达式 squares_gen = (x**2 for x in range(5)) for sq in squares_gen: print(sq) # 依次输出: 0, 1, 4, 9, 16
2.3生成器的优点
- 节省内存:生成器按需生成值,而不是一次性将所有值加载到内存中。
- 惰性求值:只有在需要时才计算值,这可以提高性能。
- 无限序列:生成器可以表示无限序列,因为它们按需生成值,而不需要在内存中存储整个序列。
- 可复用性和模块化:生成器函数可以封装复杂的逻辑,并在需要时重复使用。
python 函数式编程
函数式编程(Functional Programming)是一种编程范式,它将计算过程视为数学上的函数求值,并避免使用状态变化和可变数据。在函数式编程中,函数是一等公民,意味着函数可以作为参数传递给其他函数,也可以作为返回值从其他函数中返回。
1.函数式编程的核心概念
纯函数:纯函数是函数式编程的基础。纯函数对于相同的输入始终返回相同的输出,并且不依赖于或修改任何外部状态。这意味着纯函数没有副作用。
不可变性:在函数式编程中,数据通常是不可变的,即一旦创建,就不能更改其值。如果需要新的值,通常会创建数据的新副本。这有助于避免由于数据状态变化而导致的错误和复杂性。
高阶函数:高阶函数是指接受函数作为参数或返回函数的函数。这是函数式编程中的一个常见特性,允许函数被用作一等公民。
闭包:闭包是指能够捕获并存储其所在作用域中的变量的函数。闭包使得函数能够记住并访问其创建时的环境,这对于创建具有私有状态和行为的函数非常有用。
函数组合:函数组合是将多个函数组合成一个新函数的过程。这允许你将简单的函数组合成更复杂的函数,而不需要修改现有的函数。
柯里化(Currying):柯里化是将接受多个参数的函数转换为一系列接受单一参数的函数的技术。这有助于将函数分解为更小的、更可重用的部分。
2.Python中的函数式编程
Python虽然不是纯函数式编程语言(它支持面向对象编程和命令式编程),但它提供了许多函数式编程的特性,使得在Python中编写函数式代码成为可能。
匿名函数(lambda表达式):Python中的
lambda
表达式允许你快速定义简单的匿名函数。内置的高阶函数:Python的内置函数如
map()
、filter()
和reduce()
(需要通过functools
模块导入)都是高阶函数,它们接受函数作为参数。列表推导式和生成器表达式:这些表达式允许你以声明性的方式创建列表或生成器,而无需显式地编写循环。
模块和包:Python的模块和包系统使得函数和数据的重用变得容易。
装饰器:装饰器是Python中的一个高级特性,它允许你在不修改现有函数代码的情况下,向函数添加额外的功能。
函数式编程库:Python有许多第三方库,如
functools
、itertools
和operator
,它们提供了额外的函数式编程工具。此外,还有像toolz
和fn.py
这样的库,它们提供了更丰富的函数式编程功能。
# 使用lambda表达式和map()函数 numbers = [1, 2, 3, 4, 5] squared = list(map(lambda x: x ** 2, numbers)) print(squared) # 输出: [1, 4, 9, 16, 25] # 使用filter()函数和匿名函数 even_numbers = list(filter(lambda x: x % 2 == 0, numbers)) print(even_numbers) # 输出: [2, 4] # 使用列表推导式 squares_with_list_comprehension = [x ** 2 for x in numbers] print(squares_with_list_comprehension) # 输出: [1, 4, 9, 16, 25] # 使用reduce()函数(需要先从functools导入) from functools import reduce sum_of_squares = reduce(lambda x, y: x + y ** 2, numbers, 0) print(sum_of_squares) # 输出: 55(1 + 4 + 9 + 16 + 25)
3.内置高阶函数。
常用内置高阶函数:
(1)map(函数,可迭代对象)
使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象。
# 将一个列表中的每个数字平方 numbers = [1, 2, 3, 4, 5] squared_numbers = list(map(lambda x: x ** 2, numbers)) print(squared_numbers) # 输出: [1, 4, 9, 16, 25]
(2)filter(函数,可迭代对象)
根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。
# 过滤出一个列表中的偶数 numbers = [1, 2, 3, 4, 5, 6] even_numbers = list(filter(lambda x: x % 2 == 0, numbers)) print(even_numbers) # 输出: [2, 4, 6]
(3)sorted(可迭代对象, key=函数, reverse=True)
排序,返回值为排序后的列表结果。
# 按字符串长度对列表进行排序 words = ["apple", "banana", "cherry", "date"] sorted_words = sorted(words, key=len) print(sorted_words) # 输出: ['date', 'apple', 'banana', 'cherry']
(4)max(可迭代对象, key = 函数)
根据函数获取可迭代对象的最大值。
(5)min(可迭代对象,key = 函数)
根据函数获取可迭代对象的最小值。
4.函数作为返回值
4.1闭包
闭包(closure)是指一个函数对象,它记住了其创建时的环境(即外部作用域中的变量绑定)。简而言之,闭包是一个函数,它内部引用了外部作用域中的变量,并且这个引用在函数被返回或传递给其他函数后仍然有效。
闭包的一个关键特性是,即使外部函数已经执行完毕并返回,闭包仍然可以访问外部函数的局部变量。这是因为Python的函数对象在创建时会捕获一个对当前命名空间的引用,这个命名空间包含了函数定义时可见的所有局部变量和全局变量。
闭包必须满足以下三个条件:
必须有一个内嵌函数
内嵌函数必须引用外部函数中变量
外部函数返回值必须是内嵌函数。
4.2装饰器
Python装饰器(decorators)是一种高级功能,它允许你在不修改原有函数或方法定义的情况下,给函数或方法添加额外的功能。装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数或可调用对象。这个新的函数会扩展原有函数的行为。
装饰器的语法使用@
符号,它应该放在被装饰的函数或方法的定义之前。当你使用@decorator_name
语法时,Python会自动将紧跟在@
后面的函数名(即decorator_name
)作为装饰器,并将其应用到下面的函数定义上。
函数装饰器的语法:
def 装饰器函数名(fn): 语句块 return 函数对象 @装饰器函数名 <换行> def 被装饰函数名(形参列表): 语句块
def make_multiplier(factor): """ 创建一个函数,该函数接受一个数字并返回该数字乘以factor的结果。 """ def multiplier(number): return number * factor return multiplier # 使用make_multiplier函数创建一个乘以2的函数 double = make_multiplier(2) # 调用返回的函数 print(double(5)) # 输出: 10 # 使用make_multiplier函数创建一个乘以3的函数 triple = make_multiplier(3) # 调用返回的函数 print(triple(5)) # 输出: 15
在这个例子中,
make_multiplier
是一个高阶函数,它接受一个参数factor
并返回一个内部定义的函数multiplier
。multiplier
函数接受一个参数number
并返回number
乘以factor
的结果。通过调用make_multiplier
并传递不同的factor
值,我们可以创建具有不同乘法因子的函数。
这种技术非常有用,因为它允许你动态地创建函数,这些函数的行为可以根据创建它们时提供的参数来改变。这提供了比静态地定义多个具有相似功能但参数不同的函数更加灵活和可维护的代码。
标签:__,进阶,迭代,Python,生成器,numbers,print,函数 From: https://blog.csdn.net/2301_77084486/article/details/143098122