• 第三十篇 迭代器、三元表达式与列表推导式、字典生成式、生成器、递归


    第三十篇 迭代器、三元表达式与列表推导式、字典生成式、生成器、递归

    一、迭代器

    须知

    迭代器协议:一个对象支持以下两个方法就是迭代器:1.返回迭代器本身;2.返回下一个元素

    1、可迭代对象(Iterable)

    1.但凡有__iter__()方法的对象,都是可迭代对象

    s = str()   # 字符串
    s.__iter__()
    l = list()  # 列表
    l.__iter__()
    t = tuple() # 元组
    t.__iter__()
    d = dict()  # 字典
    d.__iter__()
    se = set()  # 集合
    s.__iter__()
    with open('x.txt','a',encoding='utf8') as f:
        f.__iter__()  # 文件
    

    2.可迭代对象使用__iter__()方法,返回的是一个迭代器

    3.凡是可作用于for循环的对象都是可迭代对象(Iterable)

    4.迭代器(Iterator)一定是可迭代对象,可迭代对象不一定是迭代器。文件既是可迭代对象又是迭代器

    5.只有字符串和列表是依赖索引取值的,而其他的可迭代对象都无法依赖索引取值,因此我们需要找到一个方法能让其他的可迭代对象不依赖索引取值

    2、迭代器对象(Iterator)

    1.可迭代对象执行__iter__()方法得到的返回值,就是迭代器对象

    2.迭代器内置有__next__()方法,执行该方法会拿到迭代器对象中的一个值

    3.迭代器对象通过使用__iter__()方法得到的返回值就是它本身

    4.迭代器的特点:

    • 1.(惰性)省空间。迭代器并不是把所有的元素提前计算出来,而是在需要的时候才计算返回
    • 2.支持无限个元素,而列表等可迭代对象就没法容纳无限个元素
    • 3.迭代器对象表示的是一个数据流,它可以不断使用__next__()方法连续返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看作是一个我们无法预知其长度的有序序列

    5.迭代器的缺点:

    • 1.取值麻烦,只能一个一个取,并且只能往后取,值取了就没了
    • 2.无法使用len()方法获取长度

    3、for循环原理

    1.for 循环称为迭代器循环,in后面必须是可迭代对象

    2.因为迭代器使用__iter__()后还是迭代器本身,因此for循环也可以用于迭代器

    3.总结:for循环本质是将可迭代对象变成迭代器,然后用__next__()方法将容器中的值一个一个取出,直到没有值然后捕捉异常,终止循环

    二、三元表达式与列表推导式

    1.三元表达式

    格式:条件成立时返回值 if 条件 else 条件不成立时的返回值

    x = 1
    print(f'x if x == 0 else 666)
    

    2. 列表推导式

    格式:[i for i in 可迭代对象] 最前面的i是表达式,中间的i是逐个元素

    三、字典生成式

    1.格式:{ i:i*2 for i in range(8) }

    2.zip()方法:

    • 1.zip()函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表
    • 2.格式:zip([iterable,......]) 一个或多个可迭代对象
    keys = ['name','age','gender']
    values = ['liu',20,'male']
    res = zip(keys,values)
    print(type(res))   # zip
    for i in res:
    	print(i)
    '''
    ('name', 'liu')
    ('age', 20)
    ('gender', 'male')
    '''
    
    l1 = ['name','age','gender']
    l2 = ['liu',20,'male']
    dic = dict(zip(l1,l2))
    

    四、生成器(Generator)

    1.通过列表生成式,我们可以直接创建一个列表,但受内存限制,列表容量肯定是有限的,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素,而不必创建完整的列表,节省空间,在python中,这种一边循环一边计算的机制,称为生成器

    2.yield的意思是生产,在函数中但凡出现yield关键字,再调用函数,就不会继续执行函数体代码,而是返回一个值

    def f():
        yield 1
        yield 2
    f_iterator = f()  # 用yield接收返回值的函数,在调用时会变成生成器
    for i in iterator:
        print(item)  # 1   2
    

    3,yield:1.yield提供了一种自定义迭代器的方法,2.yield可以暂停住函数,并提供当前的返回值

    def my_range(*args):
    	start = 0
    	step = 1
    	if (len(args)) == 1:
    		end = args[0]
    	elif len(args) == 2:
    		start = args[0]
    		end = args[1]
    	elif len(args) == 3:
    		start = args[0]
    		end = args[1]
    		step = args[2]
    	else:
    		raise('超出参数个数')
    	while start < end:
    		print(start)
    		start += step	
    

    4.生成器的本质就是迭代器,但又不限于迭代器,且生成器提供了非常方便的自定义迭代器的途径

    5.要创建一个生成器,有多种方法:

    • 1.生成器表达式。把一个列表生成式中的 [] 换成 () 即可
    l = [x*x for x in rang(10)]   # 一筐鸡蛋
    print(type(l))
    G = (x*x for x in rang(10))   # 一只老母鸡
    print(type(G))
    
    • 2.用yield返回函数的值(如果一个函数定义中包含yield关键字,那么这个函数就不是一个普通的函数,而是一个生成器)
    def fib(n):
    	c,a,b = 0,0,1
    	while c < n:
    		yield b
    		a,b = b,a+b
    		n += 1
    

    6.yield和return的异同

    • 相同:两者都是在函数内部使用,都可以返回值,并且没有类型和个数限制
    • 不同:return只能返回一次,yield可以返回多次

    五、递归

    1.递归是一种特殊的嵌套使用,它在调用函数的过程中,会直接或间接的调用自己

    2.递归:直接调用或间接调用自身

    • 1.直接调用
    def f(n):
    	if n < 2:
    		print(n)
    	else:
    		f(n-1)
    
    • 2.间接调用
    def f1():
    	f2()
    	
    def f2():
    	f1()
    

    3.递归必须要有两个明确的阶段:

    • 1.递推:一层一层递归调用下去,进入下一层递归的问题规模将会减小
    • 2.回溯:递归必须要有一个明确的结束条件,在满足该条件后开始一层一层回溯
      递归的精髓在于通过不断的重复逼近一个最终的结果
  • 相关阅读:
    jQuery Mobile方向感应事件
    Linq-多条件查询
    linux top命令详解
    在Python中调用C++,使用SWIG
    linux下core文件调试方法
    如何设置、查看以及调试core文件
    标准C++中的string类的用法总结(转)
    实用make最佳实践
    GDB多进程调试(转)
    GDB详解
  • 原文地址:https://www.cnblogs.com/itboy-newking/p/11038744.html
Copyright © 2020-2023  润新知