迭代:for 循环从列表[1,2,3]中取元素,这种遍历过程就被称作迭代
可迭代的对象有:字符串、元祖、列表、字典这类集合元素可以进行迭代处 可迭代的对象里面
a = [1, 2, 3]
for i in a:
print(i)
上述例子中,for 循环怎么知道谁是可迭代的对象呢?换个说法,我们的对象需要满足什么样的条件,就可以被for循环一个一个的取出来呢?我们就必须满足for的要求,这个要求就叫做“协议”!!
所谓协议就是类的内部实现了_iter()__和__next()__方法这两个魔法方法或者特殊方法,
只要实现了这两个特殊方法,这个对象就是可迭代的对象。可以被循环可以被迭代
当执行一个for循环的时候,迭代一个列表时,底层到底做了什么呢,
调用可迭代对象__inter__方法返回一个迭代器对象,(iterator)
不断调用迭代器__next__方法返回元素
直到迭代完成后,处理StopIteration
我们用上述方法实现一下:
a = [1, 2, 3]
aa = iter(a)
while True:
print(next(aa))
结果:
改进,使用try,catch捕获异常
a = [1, 2, 3]
aa = iter(a)
while True:
try:
print(next(aa))
except StopIteration:
break
和for循环的结果一样:效率比for循环高一点
iter() : 这个方法可以把任何一个可迭代对象转成迭代器,然后使用next的方法去循环取元素
迭代器(Iterator) : 迭代器是一个可以记住遍历位置的对象,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,迭代器往前不会后退!!
类型转换:
如何把一个迭代器转回成一个列表或者字典呢??????python 的高阶函数经常有,例子
a = [1, 2, 3]
print(map(lambda x: x ** 2, a))
结果,
为什么返回了迭代器,而不是一个列表呢 ? 会的到一个迭代器对象,而不是内容本身,惰性算法推倒时,会节省大量的内存空间,用一个生产一个,好处就是,执行效率高、节省内存资源、提升语言的性能
在python2 中会直接得到1,4,9,但是在python3中就不是这样了,返回的是一个迭代器
为什么python中返回一个迭代器而不是列表??
迭代器是不会占用内存空间的,返回的是一个列表式,是一个算法,告诉你数据是怎么生成的,需要的时候会被执行生成
for i in map(lambda x: x ** 2, a):
print(i)
返回:
1
4
9
python3最重要的变更是:返回迭代器,而不是内容本身,节省内容空间,提升语言性能
判断一个对象是否是迭代器或可迭代对象
from collections.abc import Iterator, Iterable
xx = [1, 2, 3]
bb = map(lambda x: x ** 2, xx)
print(isinstance(xx, Iterable))
print(isinstance(xx, Iterator))
print(isinstance(bb, Iterable))
print(isinstance(bb, Iterator))
结果:
如何定义一个可迭代的对象??例子
class Classes(object):
"""
班级类
"""
def __init__(self, number):
self.number = number
self.students = []
self.n = 0
def add(self, name, age):
self.students.append((name, age))
a = Classes('1-1')
a.add('张三', 7)
a.add('李四', 3)
for i in a:
print(i)
结果提示,这个对象不是可迭代的
现在我们改动一下,把他改成一个可迭代对象如图:
实现__iter__和__next__方法的对象都是迭代器,__iter__返回的是迭代器自身,__next__返回容器的下一个数值
class Classes(object):
"""
班级类
"""
def __init__(self, number):
self.number = number
self.students = []
self.n = 0
def add(self, name, age):
self.students.append((name, age))
def __iter__(self):
return self
def __next__(self):
if self.n < len(self.students):
n = self.n
self.n += 1
return self.students[n]
else:
raise StopIteration
a = Classes('1-1')
a.add('张三', 7)
a.add('李四', 3)
for i in a:
print(i)
结果:
========================================================
解释:通过列表生成式,我们可以直接创建一个列表,但是受到内存的限制,列表容量肯定式有限的,而且我们创建100万个元素的列表,不仅占用很多内存空间,如果我们访问前几个,那么后面很大的内存空间白白浪费了,
所以如果列表元素可以按照某种算法推算出来,我们是否可以在循环的过程中不断推断后续的元素
这样可以不必创建完整的list,从而节省很大的空间,在python中一边循环一边计算的机制,被称为生成器
生成器也是一种迭代器,但是只能对其迭代一次,这是因为他们并没有把所有的值存储在内存中,而是运行时生成值
列表生成式,一行表示出来,以下等价
a = [i for i in range(0, 10)]
a = []
for i in range(0,10):
a.append(i)
生成器的一个例子:
# 列表生成器
a = [i for i in range(0, 10)]
print(type(a))
# 生成器表达式
b = (i for i in range(0, 10))
print(type(b))
当生成算法比较复杂时,我们需要准备一个函数,生成器函数,用yield代替return:
例子,原始写法和生成器写法对比:生成器特点:
代码行数更少,代码更易读,时效更高,占用空间更小
========================================================
装饰器
1: 装饰器是用来装饰函数的,可能是原始函数不太丰富
首先先了解以下闭包的含义:
首先函数的参数可以是函数---------高阶函数,
函数的内部可以定义函数--------内部函数
但是外部的构造者无法访问内部的函数,这个就叫做闭包
例子:
def print_msg():
msg = "i m closur"
def printer():
print(msg)
return printer
结果:
外部函数最终将内部函数返回,完成了调用!!!!!!!!!!
例子:
# 函数,用来装饰其他的函数,其他函数征文执行之前或者之后,执行一些代码逻辑
def A(fun):
def printer():
print("双11机器人5折开始")
fun()
print("双11机器人5折结束")
return printer
@A
def say_hello():
print("您好")
@A
def goodbye():
print("在家")
say_hello()
结果: