码迷,mamicode.com
首页 > 编程语言 > 详细

Python 入门基础11 --函数基础4 迭代器、生成器、枚举类型

时间:2019-04-03 20:33:06      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:==   lin   反馈   param   异常处理   enum   UNC   display   内存   

今日目录:

  • 1.迭代器
  • 2.可迭代对象
  • 3.迭代器对象
  • 4.for循环迭代器
  • 5.生成器
  • 6.枚举对象

一、迭代器:

循环反馈的容器(集合类型)
每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值
技术图片
l = [1, 2, 3]
count = 0
while count<len(l):
    print(l[count])
    count += 1
View Code
1.1 为什么要有迭代器?
字符串、列表、元组可以通过索引的方式迭代取出其中包含的元素
字典、集合、文件等类型,没有索引,只有通过不依赖索引的迭代方式才能取值,即迭代器

二、可迭代对象

2.1 什么是可迭代对象
可迭代对象指的是内置有__iter__()方法的对象,即obj.__iter__()
技术图片
str,list,tuple,dict,set,range(),file,迭代器对象,enumerate(),生成器都是可迭代对象,即:
[].__iter__()
{}.__iter__()
().__iter__()
{1,2}.__iter__()
   ......
View Code

三、迭代器对象

3.1 什么是迭代器对象
可迭代对象通过调用__iter__()方法得到迭代器对象
迭代器对象可以不依赖索引取值(一次从容器中取出一个值) 
迭代器对象都有__next__方法,且通过该方法获取容器中的值,获取规则,从前往后一次一个
3.2 有哪些迭代器对象
文件类型、enumerate()、生成器是迭代器对象
open(‘a.txt‘).__iter__()
open(‘a.txt‘).__next__()
ps:    
    1.迭代器对象去一个值就少一个值
    2.取完了再取会报错  --> 可通过try对异常进行捕获,并处理
    3.上一个迭代器对象迭代取值完毕后,就取空了,如果要再取值,要重新生成迭代器对象
    4.迭代器对象不能求长度(内部值的个数)
    5.迭代器对象一定是可迭代对象,而可迭代对象不一定时迭代器对象
技术图片
# 迭代器对象
iter_obj = st1.__iter__()
print(iter_obj)  # <set_iterator object at 0x0000025B85231CF0>

print([1, 2, 3].__iter__())  # <list_iterator object at 0x0000017694B0B860>

# 迭代器对象去一个值就少一个值
print(iter_obj.__next__())  # 9
print(iter_obj.__next__())  # 2
print(iter_obj.__next__())  # 3
print(iter_obj.__next__())  # 4
print(iter_obj.__next__())  # 7
# print(iter_obj.__next__())  # 7  # 异常 StopIteration
View Code
技术图片
# 迭代器无法求长度(内部值的个数)
while True:
    try:  
        val = iter_obj2.__next__()
        print(val)
    except StopIteration:
        break
View Code

四、for 循环迭代器

自带异常处理的while循环,自动获取被迭代的对象的迭代器对象
原理:
    1.执行in后面对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
    2.执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
    3.重复过程2,直到捕捉到异常,StopIteration,结束循环
迭代器的优缺点:
    1.优点
        提过一种统一的、不依赖于索引的迭代方式
        惰性计算,节省内存
    2.缺点
        无法获取长度(只有在next完毕才知道到底有几个值)
        一次性的,只能往后走,不能往前退
技术图片
# for 循环迭代器,自带异常处理的while循环,自动获取被迭代的对象的迭代器对象
iter_obj = st1.__iter__()
for item in iter_obj:
    print(item)
print(----------------华丽的分割线-----------------------------------------------)

for item1 in st1:
    # 自动完成for item in st1.__iter__()
    # 自动完成异常处理
    print(item1)
View Code

五、生成器

包含yield关键字的函数就是生成器
def fn():
    yield ‘good‘
    
该函数名()得到的是生成器对象,且不会执行函数体

生成器的应用案例
当访问的数据资源过大,可以将数据用生成器处理,一次只获取所有内容的一条资源
技术图片
def g_fn():
    print("!!!!!!!!!!!!!!!!!!!!")
    yield 第一个

    print(@@@@@@@@@@@@@@@@@@@@@)
    yield 第二个

    print(#####################)
    yield 第三个

    print($$$$$$$$$$$$$$$$$$$$$)
    yield 第四个


g_obj = g_fn()

# 在函数内部执行一次,在遇到下一个yield时停止,且可以拿到yield的返回值
r1 = g_obj.__next__()
print(r1)

# 从上一次停止的地方继续往下走,再遇到下一个yield的时候停止,且可以拿到yield的返回值
r2 = g_obj.__next__()
print(r2)

r3 = g_obj.__next__()
print(r3)
View Code
技术图片
# 重新定义一个range()生成器

def my_range(min, max, step=1):
    # min, max = max, min
    tag = min
    while True:
        if tag >= max:
            break
        yield tag
        tag += step


range_obj = my_range(5, 10, 1)

for i in range_obj:
    print(i)
View Code

六、枚举对象

通过for循环迭代器循环遍历可迭代对象,需要知道迭代的索引

作业:
技术图片
# 1.用生成器完成自定义range方法,可以完成系统range的所有功能


def my_range(min, max= 0, step=1):

    if step > 0:  # 步长为正的
        if max == 0:  # 如果最大值为 0 --> my_range(10)
            min, max = max, min
        tag = min
        while True:
            if tag >= max:
                break
            yield tag
            tag += step

    elif step < 0:  # 步长为负的
        tag = min
        if min > max:
            while True:
                if tag <= max:
                    break
                yield tag
                tag += step

    else:   # 第三个参数不能是 0
        print("第三个参数不能是 0 !")


range_obj1 = my_range(10, 1, -2)
range_obj2 = my_range(10)  # --------可以用
range_obj3 = my_range(2, 10)  # -----可以用
range_obj4 = my_range(2, 10, 2)  # --可以用


"""
for i in range_obj1:
    print(i)
"""
View Code
技术图片
# 2.用生成器完成自定义enumerate方法,也可以为可迭代对象提供索引支持

# ls = [4, 3, 7, 5, 9]
ls = {1,2,3,4,5,6}

def my_enumerate(data):
    count = 0
    for i in data:
        yield (count, i)
        count += 1


"""
for i, v in my_enumerate(ls):
    print(i, v)
"""
View Code
技术图片
# 3.用生成器完成获取阶乘得方法,第一次next得到1的阶乘,第二次next得到2的阶乘,依次类推,

# 直接for循环,可以依次得到指定范围内得所有阶乘,eg:factorial(10),可以得到1~10之间的10个阶乘

def my_factorial(num):
    tag = 1
    for i in my_range(1, num+1):
        tag *= i
        yield tag

factorial_obj = my_factorial(10)

for i in factorial_obj:

    print(i)
"""
1
2
6
24
120
720
5040
40320
362880
3628800
"""
View Code

 

Python 入门基础11 --函数基础4 迭代器、生成器、枚举类型

标签:==   lin   反馈   param   异常处理   enum   UNC   display   内存   

原文地址:https://www.cnblogs.com/xt12321/p/10651229.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!