迭代器

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

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('') func()

day 13 - 1 迭代器的更多相关文章

  1. Java描述设计模式(13):迭代器模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.迭代器模式 1.基础概念 迭代器模式又叫游标模式,是对象的行为模式.迭代器模式可以顺序地访问一个聚集中的元素而不必暴露聚集的内部表象. 2 ...

  2. 把《c++ primer》读薄(3-2 标准库vector容器+迭代器初探)

    督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正. 标准库vector类型初探,同一种类型的对象的集合(类似数组),是一个类模版而不是数据类型,学名容器,负责管理 和 存储的元素 ...

  3. C语言字符串操作总结大全

    1)字符串操作 strcpy(p, p1)  复制字符串  函数原型strncpy(p, p1, n)   复制指定长度字符串  函数原型strcat(p, p1)   附加字符串  函数原型strn ...

  4. C语言字符串操作总结大全(超详细)

    本篇文章是对C语言字符串操作进行了详细的总结分析,需要的朋友参考下 1)字符串操作  strcpy(p, p1) 复制字符串  strncpy(p, p1, n) 复制指定长度字符串  strcat( ...

  5. c语言的字符串操作(比较详细)

    1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度 ...

  6. PHP Predefined Interfaces 预定义接口(转)

    SPL提供了6个迭代器接口: Traversable 遍历接口(检测一个类是否可以使用 foreach 进行遍历的接口) Iterator 迭代器接口(可在内部迭代自己的外部迭代器或类的接口) Ite ...

  7. 重拾C++ 基础知识总结(二)

    1.标准库string类型: 用户程序要使用string类型对象,必须包含相关头文件 #include <string> 字符串字面值与标准库string类型不是同一种类型,字符串字面值是 ...

  8. Boost程序库完全开发指南——深入C++“准”标准库(第3版)

    内容简介  · · · · · · Boost 是一个功能强大.构造精巧.跨平台.开源并且完全免费的C++程序库,有着“C++‘准’标准库”的美誉. Boost 由C++标准委员会部分成员所设立的Bo ...

  9. C语言字符串操作函数集

    1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度 ...

随机推荐

  1. redis分页

    模仿的https://www.cnblogs.com/dee0912/p/4612183.html 第一步连接redis后进行添加数据 require_once '../redis/redis.php ...

  2. 0.[Andriod]之从零安装配置Android Studio并编写第一个Android App

    0. 所需的安装文件 笔者做了几年WP,近来对Android有点兴趣,尝试一下Android开发,废话不多说,直接进入主题,先安装开发环境,笔者的系统环境为windows8.1&x64. 安装 ...

  3. Spring Cloud:多环境配置、eureka 安全认证、容器宿主机IP注册

    记录一下搭建 Spring Cloud 过程中踩过的一些坑,测试的东西断断续续已经弄了好多了,一直没有时间整理搭建过程,时间啊~时间~ Spring 版本 Spring Boot:2.0.6.RELE ...

  4. Google第三方网站登录(JavaScript SDK)

    官网:https://developers.google.com/identity/sign-in/web/ 一.创建应用 a.去谷歌控制台创建应用     网址:https://accounts.g ...

  5. 科大讯飞语音合成api

    import base64import jsonimport timeimport hashlibimport requests # API请求地址.API KEY.APP ID等参数,提前填好备用a ...

  6. 【问题解决方案】ImportError: No module named 'openpyxl'/‘xlrd’

    背景: 在jupyter notebook to_excle: 运行将dataframe保存为excel文件 df.to_excel('dataframe.xlsx') 时报错openpyxl rea ...

  7. mysql监控每一条执行的sql语句

    查看日志配置是否打开 SHOW VARIABLES LIKE "general_log%"; SET GLOBAL general_log = 'ON';   打开日志 SET G ...

  8. python多线程和多进程

    1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...

  9. vue 限制输入字符长度

    一.watch方法: <input v-model="textareaValue" type="textarea" placeholder="请 ...

  10. flex知识点归纳

    1.flex-shrink <div id="content"> <div class="box" style="backgroun ...