目录
一、可迭代类型和迭代器
Pyhton中的可迭代类型是指那些可以返回一个迭代器的对象。例如:列表、元组、字符串、字典、集合、生成器和文件对象等。
import random
import time
from collections.abc import *
# 可迭代和迭代器
class MyDatas:
def __init__(self, n):
self.datas = [i for i in range(1, n + 1)]
self.current_index = 0
def __iter__(self):
return self
def __next__(self):
if self.current_index >= len(self.datas):
raise StopIteration
else:
current = self.datas[self.current_index]
self.current_index += 1
return current
md = MyDatas(5)
print(isinstance(md, Iterable), isinstance(md, Iterator), isinstance(md, Generator))
print(next(md))
print(next(md))
print(next(md))
print(next(md))
print(next(md))
# 索引越界,抛出异常
try:
print(next(md))
except StopIteration as e:
print("迭代结束", e)
这是一个关于可迭代和迭代器的案例,首先是定义了一个class类,类中的初始函数中定义了列表推导式,魔法函数__iter__和__next__则说明了它是一个迭代器,通过对实例化的md进行isinstance判断,我们可以知道它是可迭代类型的。
迭代器的好处是既可以通过索引来拿到想要的数据,也可以通过next()来逐个获取迭代器内的数据。但是如果超出最大索引,程序会报错。
二、生成器
python中常见的生成器可以是生成器函数,也可以是元组推导式。
下方是一个元组推导式类型的生成器:
t0 = (i for i in range(1, 1000000))
print(t0)
print(isinstance(t0, Iterable), isinstance(t0, Iterator))
print(isinstance(t0, Generator))
生成器是可迭代类型,是迭代器,是生成器,它的优点是占用空间小,缺点是不能通过索引取到想要的值,只能逐个获取。
下方是一个函数类型的生成器:
def my_fun():
yield 2
yield 5
yield 10
return 200
datas = my_fun()
for data in datas:
print(data)
每当函数执行到yield
语句时,它会返回一个迭代器对象,该对象指向下一个yield
语句的值,可以通过遍历迭代器来获取其中的值。
三、装饰器
提到装饰器就要提到闭包的三个概念:一是外部函数嵌套内部函数,二是外部函数返回内部函数的函数名,三是内部函数可以访问外部函数的局部变量。
下方是一个计算排序的时间开销的装饰器:
def time_cost(f):
def calc():
start = time.time()
f()
print(f"函数{f.__name__}的时间消耗为:{time.time() - start}")
return calc
datas = [random.randint(0, 10000) for i in range(10000)]
datas2 = datas.copy()
@time_cost
def my_sort1():
datas.sort()
print(datas)
@time_cost
def my_sort2():
datas3 = sorted(datas2)
print(datas3)
# # 这里的my_sort1和my_sort2是返回的内部函数的函数名calc
# my_sort1 = time_cost(my_sort1)
# my_sort2 = time_cost(my_sort2)
# # 执行my_sort1和my_sort2就是执行calc
# my_sort1()
# my_sort2()
# 在函数前面使用@语法就可以省略上面的繁琐步骤,这就是装饰器
my_sort1()
my_sort2()
装饰器就是在不改变原函数内容的情况下给函数增加新的功能,上方代码通过装饰器来计算sort和sorted的时间开销,比较两个排序方式的效率。