zoukankan      html  css  js  c++  java
  • day 13

    迭代器

    首先我们查看下列类型拥有的所有方法(会显示很多)

    print(dir([])) 
    print(dir({})) 
    print(dir('')) 
    print(dir(range(10)))
    #求下上面列表中方法的交集
    ret = set(dir([]))&set(dir({}))&set(dir(''))&set(dir(range(10))) #set 转化为列表
    print(ret)
    
    #可以注意到都有这两个双下方法
    # __init__  __iter__
    
    #我们来举一个双下方法的例子
    #举例:列表的相加
    
    print([1].__add__([2]))
    print([1]+[2]) #实际执行的是 print([1].__add__([2]))
    
    #接着我来看一下 int 类型
    for i in 123:
        print(i)
    
    #不可被循环的会提示该报错:TypeError: 'int' object is not iterable(iterable:可迭代的)
    #原因是 int 类型没有该方法 __iter__

    判断数据类型中是否有 __iter__ 方法

    print('__iter__' in dir(int))   #False
    print('__iter__' in dir(bool))  #False
    print('__iter__' in dir(list))
    print('__iter__' in dir(dict))
    print('__iter__' in dir(set))
    print('__iter__' in dir(tuple))
    print('__iter__' in dir(enumerate([])))
    print('__iter__' in dir(range(1)))
    
    #方法之间也可以相减 去重(主要是查看 并没有什么用)
    print(set(dir([].__iter__())) - set(dir([])))  

    只要是能被 for 循环的数据类型 就一定拥有 __iter__ 方法,一个列表执行了 __iter__() 之后的返回值就是一个迭代器

    print([].__iter__())
    <list_iterator object at 0x0000000000A8F2E8> #iterator 迭代器,返回的是一个内存地址
    #使用 __next__ 一个一个的取值
    l = [1,2,3]
    iterator = l.__iter__()
    print(iterator)          #列表是可以迭代的,当可迭代的后面加上 .__iter__() 方法,就可以得到一个迭代器,返回是一个内存地址
    print(iterator.__next__())
    print(iterator.__next__())
    print(iterator.__next__())  #当无值可取时会抛出 StopIteration 的异常
    print(iterator.__next__())  #for 循环就是一个迭代器 当无值可取时也会出现该异常,但是 for 已经帮我们处理了
    
    #__length_hint__ 计算元素个数
    print([1,'a','bbb'].__iter__().__length_hint__())

    Iterable 可迭代的    ——>  __iter__  只要含有 __iter__ 方法的都是可迭代的 —— 可迭代协议
    [].__iter__() 迭代器 ——>  __next__   通过 next 就可以从迭代器中一个一个的取值

    简单的证明一下上面的结论

    from collections import Iterable
    from collections import Iterator
    
    class A:
        def __iter__(self):pass #在这两处添加注释 然后查看下面的输出结果
        def __next__(self):pass #两次查看做下对比
    
    a = A()
    print(isinstance(a,Iterator))
    print(isinstance(a,Iterable))

    迭代器的概念

    迭代器协议 —— 内部含有 __next__ 和 __iter__ 方法的就是迭代器

    迭代器协议和可迭代协议

    要含有 __iter__ 方法的都是可迭代的 —— 可迭代协议 
    部含有 __next____iter__ 方法的就是迭代器 —— 迭代器协议
    可以被for循环的都是可迭代的
    可迭代的内部都有 __iter__ 方法
    只要是迭代器,一定是可迭代的
    可迭代的 .__iter__() 方法就可以得到一个迭代器
    迭代器中的 __next__() 方法可以一个一个的获取值

    for 循环

    for 循环其实就是在使用迭代器  

    只有 是可迭代对象的时候 才能用 for
    当我们遇到一个新的变量,不确定能不能 for 循环的时候,就判断它是否可迭代(判断它内部有没有 __iter__ )

    for 循环的运行逻辑

    for i in l:
        pass
    iterator = l.__iter__()
    iterator.__next__()

    迭代器的好处

    从容器类型中一个一个的取值,会把所有的值都取到。
    节省内存空间(因为它不是一下子发内容存到内存当中的,而是一条一条的读取)
    迭代器并不会在内存中再占用一大块内存,
    而是随着循环 每次生成一个
    每次 next 每次给我一个

    装饰器复习

    装饰器
    装饰器的作用:在不改变原来函数的调用方式的情况下,在这个函数的前后添加新的功能
    完美的符合了一个开发原则:开放封闭原则
      对扩展的是开放的
      对修改是封闭的

    基础的装饰器

    from functools import wraps
    def wrapper(func):
        @wraps(func)
        def inner(*args,**kwargs):
            '''在函数被调用之前添加的代码'''
            ret = func(*args,**kwargs)   # func是被装饰的函数 在这里被调用
            '''在函数被调用之后添加的代码'''
            return ret
        return inner
    #使用 —— @wrapper
    @wrapper
    def func():   #inner
        pass

    带参数的装饰器

    @wrapper -- > @warapper(argument)
    #三层嵌套函数
    def outer(形参):
        def wrapper(func):
            def inner(*args,**kwargs):
                '''在函数被调用之前添加的代码'''
                ret = func(*args,**kwargs)   # func是被装饰的函数 在这里被调用
                '''在函数被调用之后添加的代码'''
                return ret
            return inner
        return wrapper
    
    @outer(True)
    def func():
        pass

    多个装饰器装饰一个函数

    from functools import wraps
    def wrapper1(func):
        @wraps(func)
        def inner(*args,**kwargs):
            print('before 1')
            print('******')
            ret = func(*args,**kwargs)   # func是被装饰的函数 在这里被调用
            '''在函数被调用之后添加的代码'''
            return ret
        return inner
            
    def wrapper2(func):
        @wraps(func)
        def inner(*args,**kwargs):
            print('before 2')
            ret = func(*args,**kwargs)   # func是被装饰的函数 在这里被调用
            '''在函数被调用之后添加的代码'''
            return ret
        return inner
    
    @wrapper1
    @wrapper2
    def func():
        print('111')
    
    func()
  • 相关阅读:
    MapReduce的工作机制
    1023. Have Fun with Numbers (20)
    Javascript MVC 学习笔记(二) 控制器和状态
    Chapter 1 Securing Your Server and Network(5):使用SSL加密会话
    《MySQL必知必会学习笔记》:子查询
    C# 打开指定的目录 记住路径中 / 与 的使用方法
    JAVA虚拟机、Dalvik虚拟机和ART虚拟机简要对照
    应届生面试准备之道
    一致性hash
    android 关于listview scrollview 底部 控件无法显示的两个解决方案
  • 原文地址:https://www.cnblogs.com/ysging/p/10089548.html
Copyright © 2011-2022 走看看