四:迭代器生成器

一:迭代器

暂时不涉及到自定义迭代器,涉及到了再补,暂时知道for循环的原理就可以了.

1有__iter__就是可迭代的,也叫可迭代协议

2双下方法:c语言写好了的内置方法,可以用不止一种的方式调用

3迭代取值的工具
4可迭代对象执行__iter__得到的返回值就是迭代器.
5可以把它看作数据流,只能前进不能后退,迭代到头了就会从内存消失
6如果还有__next__方法,那么就是迭代器了,光有__next__就什么都不是
7迭代器的另一个好处是节省内存,不会一次全在内存中生成,而是随着循环每次生成一个
8只关心当前数据,和下一个数据的位置,其他数据没有在内存当中
9迭代器一定是可迭代的
10很少自己写迭代器,都是用for去循环可迭代对象,当到头没有数据报StopIteration异常,for循环完美的处理了这个异常.
11.for循环的本质就是通过__iter__拿到迭代器,然后不断调用__next__获取数值,直到报异常并处理掉
迭代器更多的是从已经存在的数据结构中获取值,就算没有索引也可以不断获取后面的数据,迭代器知道这些就可以了.
迭代器几乎不会自己定义
class Test:
    pass
test = Test()
for i in test:
    print(i)
#TypeError: 'Test' object is not iterable
for遍历不可迭代对象报错
class Test:
    def __iter__(self):
        return self

test = Test()
for i in test:
    print(i)
#TypeError: iter() returned non-iterator of type 'Test'
for遍历可迭代对象,但不是迭代器报错
class MyStudents:
    """
    自定义一个迭代器对象
    """
    stu_list = []

    def __init__(self, *args):
        names = args
        self.position = 0
        for name in names:
            self.stu_list.append(name)
    
    #对象本身就是迭代器,返回自身
    def __iter__(self):
        return self

    def __next__(self):
        if self.position < len(self.stu_list):
            item = self.stu_list[self.position]
            self.position+=1
            return item
        else:
            raise StopIteration()

    def __str__(self):
        return self.stu_list.__str__()

    def add_student(self,stu_name):
        self.stu_list.append(stu_name)

stus = MyStudents("张三","李四")
stus.add_student("王五")
stus.add_student("赵六")
print(stus)
for i in stus:
    print(i)
自定义迭代器

二:生成器本质是迭代器

优点:不会一下子在内存中生成全部数据,调用一次__next__才生成一个数据
生成器保存的是生成数据的逻辑,而非具体数据,调用一次生成一次数据
生成器更多的是不断的根据外界条件来生成不同的值到内存中
1生成器表达式:相同的生成数据的逻辑,后面说
2生成器函数:含有yield的函数就是生成器函数,且根据不同的条件生成不同的数据
1 def gen_test():
2     for i in range(20):
3         yield "test%s" % i
简单生成器

生成器函数调用了只会生成一个generator对象,不会执行里面的代码

只有next(g)才会执行到第一个yield结束,并将值返回

正好for循环就可以不断的调用next()

三:表达式

列表推导式:一次性生成全部数据

li=[i**2 for i in range(10)]
print(li)
View Code

for遍历每个元素,按照开头的规则生成每个元素,for的简写形式

多层嵌套
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
#先for的外面的大列表,然后for里面的小列表
#推导式的缺点是无法打断点,debug
ret = [li for name in names for li in name if li.count("e")>=2]
print(ret)
View Code

生成器表达式:不会全部数据一次性生成到内存中

只把列表生成式外层中括号换成小括号即可

字典推导式:原理还是for循环遍历的是key

合并大小写对应的value值,将k统一成小写
mcase2 = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
ret2 = {k.lower():mcase2.get(k.lower(),0)+mcase2.get(k.upper(),0) for k in mcase2}
print(ret2)
View Code

集合推导式

集合推倒式,和列表推到式就差一个{},多了去重的功能
squared = {x**2 for x in [1, -1, 2]}
print(squared)
View Code
看十遍不如自己写一遍!巩固基础,纵横开拓!
原文地址:https://www.cnblogs.com/gyxpy/p/11559613.html