自定义迭代器

一 、生成器与yield

  '''
我们得到一个迭代器通常都是调用可迭代对象的__iter__方法 ,例如 list.iter() 得到一个迭代器,
但是当list很大时候,就违背了python的初衷,假设我们要创造一个包含1000w个值的可迭代对象,总不可能先把
这1000w个值放入列表,然后调用__iter__() 方法吧,太占内存 ,必须得提供一种机制打破python内置的产生
迭代器的方式 ,所以自定义迭代器应运而生,即生成器。
在Python中, 一边循环一边计算的机制, 称为生成器:generator, 若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象
'''

自定义range函数

  def my_range(start,stop,step=1):   # 自定义range函数
print('start...')
while start < stop:
yield start
start+=step
print('end...') g=my_range(0,3)
print(g)
<generator object my_range at 0x01E2A808>
如何得到自定义的迭代器:
在函数内一旦存在yield关键字,调用函数并不会执行函数体代码
会返回一个生成器对象,生成器即自定义的迭代器 """
如果函数体代码中含有多个yield关键字 执行一次__next__返回后面的值并且让代码停留在yield位置
再次执行__next__基于上次的位置继续往后执行到下一个yield关键字处
如果没有了 再执行也会报错 StopIteration
"""

生成器本身就是一个迭代器

  print(g.__iter__) # <method-wrapper '__iter__' of generator object at 0x01AFB878>
print(g.__next__) # <method-wrapper '__next__' of generator object at 0x01AFB878>
'''生成器内置有__iter__和__next__方法,所以生成器本身就是一个迭代器'''

用next(生成器)触发生成器所对应函数的执行

  print(next(g)) # 触发函数执行直到遇到yield则停止,将yield后的值返回,并在当前位置挂起函数
start...
0
print(next(g)) # 再次调用next(g),函数从上次暂停的位置继续执行,直到重新遇到yield...
1
print(next(g)) # 周而复始...
2
print(next(g)) # 触发函数执行没有遇到yield则无值返回,即取值完毕抛出异常结束迭代
end...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration 既然生成器对象属于迭代器,那么必然可以使用for循环迭代,如下:
for i in g:
print(i)
执行结果:
start...
0
1
2
end... '''
有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于
return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值
'''

yield关键字作用

yield最简单的解释

  yield可以理解为一个return操作,但是和return又有很大的区别,执行完return,当前函数就终止了,
函数内部的所有数据,所占的内存空间,全部都没有了。而yield在返回数据的同时,还保存了当前的执行
内容,当你再一次调用这个函数时,他会找到你在此函数中的yield关键字,然后从yield的下一句开始执行。

例一

    def num_print():
print('yield_1')
yield 'yield_1 return'
print('yield_2')
yield 'yield_2 return'
print('yield_3')
yield 'yield_3 return'
print('yield_4')
yield 'yield_4 return' for i in num_print():
print('i:',i)
执行结果:
yield_1
i: yield_1 return
yield_2
i: yield_2 return
yield_3
i: yield_3 return
yield_4
i: yield_4 return
'''
上边在循环处一直在调用函数,可以看出每次调用函数,他会执行到yield进行返回,然后下一次调用时
他会从上一次执行yield的后边继续执行
'''

例二(可以接收外界的传值(了解))

  def play():
while True:
game = yield
print(f'玩{game}')
res = play()
res.__next__()
res.send('LOL')
执行结果:
玩LOL

生成器表达式

语法

  (返回值 for 元素 in 可迭代对象 if 条件)
返回一个生成器,生成器也是一个对象,属于中间值
g = (i ** 2 for i in range(5)) # 将使用生成器表达式得到的生成器对象赋给一个变量g
print(g) '''输出:
<generator object <genexpr> at 0x109835b10>
'''
print(g.__next__())
"""生成器内部的代码只有在调用__next__迭代取值的时候才会执行"""
主要功能是,代码优化,节省存储空间。

生成器表达式和列表生成式的区别

模块

简介

  在Python中有一个概念叫做模块(module),这个和C语言中的头文件以及Java中的包很类似,比如在
Python中要调用sqrt函数,必须用import关键字引入math这个模块
说的通俗点:模块就好比是工具包,要想使用这个工具包中的工具(就好比函数),就需要导入这个模块

模块的来源

  目前有3个来源
1.内置的模块
无需下载 解释器自带 直接导入使用即可
2.自定义模块
自己写的代码 封装成模块 自己用或者发布到网上供别人使用
3.第三方模块
别人写的发布到网上的 可以下载使用的模块(很多牛逼的模块都是第三方)

导入模块的方法

第一种:import

    在Python中用关键字import来引入某个模块,比如要引用模块math,就可以在文件最开始的地方用
import math来引入。
当解释器遇到import语句,如果模块在当前的搜索路径就会被导入。 在调用math模块中的函数时,必须这样引用:
模块名.函数名
这种方式必须加上模块名调用,因为可能存在这样一种情况:在多个模块中含有相同名称的函数,此时如
果只是通过函数名来调用,解释器无法知道到底要调用哪个函数。所以如果像上述这样引入模块的时候,调用
函数必须加上模块名。 有时候我们只需要用到模块中的某个函数,只需要引入该函数即可,此时可以用下面方法实现:
from模块名import函数名1,函数名2....
'''
通过这种方式引入的时候,调用函数时只能给出函数名,不能给出模块名,但是当两个模块中含有相同
名称函数的时候,后面一次引入会覆盖前一次引入。也就是说假如模块A中有函数function( ),在模块B中也
有函数function( ),如果引入A中的function在先、B中的function在后,那么当调用function函数的时
候,是去执行模块B中的function函数。
'''
如果想一次性引入math中所有的东西,还可以通过from math import *来实现

第二种:from…import

  Python的from语句让你从模块中导入一个指定的部分到当前命名空间中

  语法如下:

  from 模块名 import name,func1,func2(需要导入的函数或者变量)

  例如,要导入模块fib的fibonacci函数,使用如下语句:

  from fib import fibonacci

  注意:
不会把整个fib模块导入到当前的命名空间中,它只会将fib里的fibonacci单个引入
"""
1.重复导入也只会导入一次
2.使用模块名称空间中的名字不需要加模块名前缀 直接使用即可
3.但是from...import的句式会产生名字冲突的问题
在使用的时候 一定要避免名字冲突
4.使用from...import的句式 只能使用import后面出现的名字
from...import...可以简单的翻译成中文
从...里面拿...来用 没有提到的都不能用 指名道姓
"""

补充

  导入模块起别名,导入模块是对模块进行重命名,也就是给模块起一个别名。
import 模块名 as mod '''
在后续使用时就可以使用这个别名
比如模块名或者变量名很复杂 可以起别名简写
''' from 模块名 import *
'''
*表示md里面所有的名字 from...import的句 式也可以导入所有的名字
如果模块文件中使用了__all__限制可以使用的名字 那么*号就会失效 依据__all__后面列举的名字
'''

图文介绍两种导包


生成器对象(自定义迭代器),自定义range方法,模块的更多相关文章

  1. Python自动化--语言基础5--面向对象、迭代器、range和切片的区分

    面向对象 一.面向对象代码示例: 1 class Test(): #类的定义 2 car = "buick" #类变量,定义在类里方法外,可被对象直接调用,具有全局效果 3 def ...

  2. python学习Day14 带参装饰器、可迭代对象、迭代器对象、for 迭代器工作原理、枚举对象、生成器

    复习 函数的嵌套定义:在函数内部定义另一个函数 闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.返回内部函数对象---->  延迟执行, 开放封闭原则: 功能可以拓展,但源代 ...

  3. day 13 迭代器、可迭代对象、迭代器对象、生成器、生成器对象、枚举对象

    迭代器大概念 # 迭代器:循环反馈的容器(集合类型)# -- 不同于索引取值,但也可以循环的从容器对象中从前往后逐个返回内部的值​# 优点:不依赖索引,完成取值# 缺点:不能计算长度,不能指定位取值( ...

  4. python之迭代器、可迭代对象、生成器、生成器对象、枚举类型

    迭代器 # 迭代器:循环反馈的容器(集合类型)# -- 不同于索引取值,但也可以循环的从容器对象中从前往后逐个返回内部的值​# 优点:不依赖索引,完成取值# 缺点:不能计算长度,不能指定位取值(只能从 ...

  5. ECMAScript 2015 迭代器协议:实现自定义迭代器

    迭代器协议定义了一种标准的方式来产生一个有限或无限序列的值,并且当所有的值都已经被迭代后,就会有一个默认的返回值. 当一个对象只有满足下述条件才会被认为是一个迭代器:它实现了一个 next() 的方法 ...

  6. python14 1.带参装饰器 | wrapper 了了解 # 2.迭代器 ***** # 可迭代对象 # 迭代器对象 # for迭代器 # 枚举对象

    ## 复习 '''函数的嵌套定义:在函数内部定义另一个函数 闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.验证执行 开放封闭原则: 功能可以拓展,但源代码与调用方式都不可以改变 ...

  7. day14带参装饰器,迭代器,可迭代对象 , 迭代器对象 ,for迭代器 , 枚举对象

    复习 ''' 函数的嵌套定义:在函数内部定义另一个函数 闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.验证执行 开放封闭原则: 功能可以拓展,但源代码与调用方式都不可以改变 装饰 ...

  8. Two---python循环语句/迭代器生成器/yield与return/自定义函数与匿名函数/参数传递

    python基础02 条件控制 python条件语句是通过一条或多条语句的执行结果(Ture或者False)来执行的代码块 python中用elif代替了else if,所以if语句的关键字为:if- ...

  9. Python 3.x自定义迭代器对象

    Python 3.x与Python 2.x之间存在着较多的语法细节差异.今天在看Python核心编程的时候,说到了自定义迭代器对象.于是动手将源码打了一遍,原书代码如下: class AnyIter( ...

随机推荐

  1. Netty + Spring + ZooKeeper搭建轻量级RPC框架

    本文参考 本篇文章主要参考自OSCHINA上的一篇"轻量级分布式 RPC 框架",因为原文对代码的注释和讲解较少,所以我打算对这篇文章的部分关键代码做出一些详细的解释 在本篇文章中 ...

  2. 彻底搞懂CSS层叠上下文、层叠等级、层叠顺序、z-index

    前言 最近,在项目中遇到一个关于CSS中元素z-index属性的问题,具体问题不太好描述,总结起来就是当给元素和父元素色设置position属性和z-index相关属性后,页面上渲染的元素层级结果和我 ...

  3. CentOS安装图形界面以及eclipse的安装

    图形界面的安装,以GNOME为例: 1.首先运行命令:yum grouplist 会显示可安装的包,可以自己选择安装. 2.运行  yum gruopinstall "GNOME" ...

  4. webpack 4.0 配置方法以及错误解决

    选取一个空目录来试验 全局安装webpack4.1之后 创建目录 mkdir webpacktest && cd webpacktes 初始化package.json npm init ...

  5. 设计模式学习笔记(十五)命令模式及在Spring JdbcTemplate 中的实现

    命令(Command)模式是指将请求封装成为一个对象,使发出请求和执行请求的责任分割开,方便将命令对象进行存储.传递.调用.增加与管理. 也就是将发送者.接收者和调用命令封装成独立的对象,来供客户端调 ...

  6. python---二叉树广度优先和深度优先遍历的实现

    class Node(object): """结点""" def __init__(self, data): self.data = dat ...

  7. 7.Arrays类

    1. Arrays类 数组的工具类java.util.Arrays Arrays类中的方法都是static修饰的静态方法,使用的时候可以直接使用类名进行调用 (而不是使用对象)(是"不用&q ...

  8. 微信小程序--设置和获取剪切板内容

    设置 wx.setClipboardData  // 复制功能 获取 wx.getClipboardData // 粘贴功能     let _this = this     wx.setClipbo ...

  9. 2021.08.09 P5658 括号树(树形结构)

    2021.08.09 P5658 括号树(树形结构) [P5658 CSP-S2019] 括号树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 太长,在链接中. 分析及代码 ...

  10. selenium模块无头化浏览器 设置不加载页面css、图片、js

    下面代码基于火狐浏览器,谷歌浏览器代码类似 from selenium import webdriver from selenium.webdriver.firefox.options import ...