1、迭代器&生成器

列表生成式

现在有个需求,列表[1,2,3,4,5,6,7,,8,9],要求把列表里的每个值加1,如何实现?

方法一:

list = [1,2,3,4,5,6,7,8,9]

for index,i in enumerate(list):
list[index] = i + 1 print(list)
运行结果:
[2, 3, 4, 5, 6, 7, 8, 9, 10]

 方法二:

list = [1,2,3,4,5,6,7,8,9]
#map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 列表list,并通过把函数 f 依次作用在 list 的每个元素上,
# 得到一个新的 list 并返回
a = map(lambda x:x+1,list)
for i in a:
print(i)
运行结果:
[2, 3, 4, 5, 6, 7, 8, 9, 10]

 其实,还有一种写法

list = [1,2,3,4,5,6,7,8,9]
a = [x+1 for x in list]
print(a)
运行结果:
[2, 3, 4, 5, 6, 7, 8, 9, 10]

 这就叫做列表生成式

 生成器

通过列表生成式,我们可以创建一个列表,但是,受到内存限制,列表容量是有限的。而且,创建一个包含100百万元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间就白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可在循环过程中不断推算出后面的元素呢?这样就不需创建完整的列表,从而节省大量空间。在python中,这种一边循环一边计算的机制,称为生成器:generator。创建一个generator,有很多中方法,第一种方法很简单,只要把列表生成式中的[]改成(),就创建了一个generator。

a = [x+1 for x in range(10)]
print(a)
a = (x+1 for x in range(10))
print(a)
运行结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
<generator object <genexpr> at 0x0000017258EF2830>

 generator要打印出来,需要通过next()函数获得generator的返回值

print(next(a))
1
print(next(a))
2

generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

上面这种不断调用next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象:

for i in a:
print(i)

generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ..

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

def fib(max):
n,a,b=0,0,1
while n<max:
print(b)
a,b=b,a+b
n +=1
return 'done' fib(10)

  

仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:

def fib(max):
n,a,b=0,0,1
while n<max:
yield b
a,b=b,a+b
n +=1
return 'done'

  这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。yield相当于一个断点

f = fib(10)
print(f.__next__())
print(f.__next__())
print("干点别的事")
print(f.__next__())
print(f.__next__())
运行结果:
1
1
干点别的事
2
3

  同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代:

for i in fib(10):
print(i)

  迭代器

我们已经知道,可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如listtupledictsetstr等;

一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

可以使用isinstance()判断一个对象是否是Iterable对象:

可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

个人理解:生成器就是迭代器

3、装饰器

软件开发原则:开放-封闭,不能改变原代码的调用方式。

  • 封闭:已实现的功能代码块不应该被修改
  • 开放:对现有功能的扩展开放

闭包函数:python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。

 import time
def timer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)#执行index原始函数
stop_time = time.time()
print('run time is %s' %(stop_time-start_time))
return res
return wrapper @timer #index=timer(index)
def index(msg):
print('in the index: ',msg)
return 1
res=index('hello world') #wrapper('hello world')
print(res)
# 装饰器执行流程:
# 1、导入time模块
# 2、定义timer函数,函数名作为变量名赋值给timer函数
# 3、@timer index赋值给timer函数
# 4、定义闭包函数wrapper,直接返回wrapper
# 5、定义index函数
# 6、执行index函数,实际是执行timer函数的返回值wrapper函数

有参装饰器

python之路6-迭代器、生成器、装饰器的更多相关文章

  1. python学习笔记(5)--迭代器,生成器,装饰器,常用模块,序列化

    生成器 在Python中,一边循环一边计算的机制,称为生成器:generator. 如: >>> g = (x * x for xin range(10)) >>> ...

  2. Python基础-迭代器&生成器&装饰器

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 我现在有个需求,看 ...

  3. Python 迭代器&生成器,装饰器,递归,算法基础:二分查找、二维数组转换,正则表达式,作业:计算器开发

    本节大纲 迭代器&生成器 装饰器  基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - ...

  4. 迭代器/生成器/装饰器 /Json & pickle 数据序列化

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需 ...

  5. 4.python迭代器生成器装饰器

    容器(container) 容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中.通常这类数据结构把所有的元素存储在内存中 ...

  6. python中的迭代器&&生成器&&装饰器

    迭代器iterator 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束. 迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外, ...

  7. Python学习——迭代器&生成器&装饰器

    一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...

  8. Python 全栈开发五 迭代器 生成器 装饰器

    一.迭代器 迭代协议:对象必须提供一个next方法,执行该方法后会返回迭代的下一项或者抛出Stopiteration异常,终止迭代.切只能往前,不能倒退. 可迭代对象:遵循迭代写一点对象就是可迭代对象 ...

  9. python中的迭代器 生成器 装饰器

    什么迭代器呢?它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()(python2中实现next())方法的对象都是迭代器,_ ...

  10. Python迭代器&生成器&装饰器

    1. 迭代器 1.1 可迭代对象(Iterator) 迭代器协议:某对象必须提供一个__next__()方法,执行方法要么返回迭代中的下一项,要么引起一个Stopiteration异常,以终止迭代(只 ...

随机推荐

  1. 【Linux】Linux上安装Nginx

    本文介绍Linux环境安装Nginx,这里用的Linux系统是CentOS 7.2. 1. 从Nginx官网下载Nginx.这里用的版本为:1.13.6. 2. 将下载下来的Nginx上传到Linux ...

  2. vue项目中vscode格式化配置和eslint配置冲突

    问题描述 使用vscode开发vue项目的时候,从远端拉下一个新的项目后,安装完依赖后跑起项目时,发现直接报了一堆语法错误:包括换行.空格.单双引号.分号等各种格式问题 因为我的 vscode 安装使 ...

  3. RelativeLayout设置wrap_content无效

    尊重劳动成果,转载请标明出处:http://www.cnblogs.com/tangZH/p/8419053.html 在做项目的过程中,遇到了一个奇怪的现象,我设置RelativeLayout为的宽 ...

  4. 如何获取Debug Android Hash Key

    在接入FaceBook第三方登录的时候,需要获取Android Hash Key. Android Hash Key即密钥散列有两种,一种是开发秘钥散列,一种是发布秘钥散列.这里主要介绍如何获取开发秘 ...

  5. 使用Python下载工具you-get下载媒体文件

    You-Get是一个基于 Python 3 的下载工具.使用 You-Get 可以很轻松的下载到网络上的视频.图片及音乐. 使用you-get下载媒体文件 1.安装Python(步骤详情见另一篇文章) ...

  6. C++ 浅拷贝与深拷贝探究

    C++浅拷贝与深拷贝探究 浅拷贝与深拷贝的概念是在类的复制/拷贝构造函数中出现的. 拷贝构造函数使用场景 对象作为参数,以值传递方式传入函数(要调用拷贝构造函数将实参拷贝给函数栈中的形参) 对象作为返 ...

  7. Linux命令学习总结:ls

    命令简介: ls命令用来列出目标目录(缺省的话为当前目录)中所有的子目录和文件.指令英文原义:list 指令所在路径:/bin/ls 执行权限:All User 命令语法: ls [OPTION].. ...

  8. Left Jion和where区别

    首先,新建两张表A和B,然后插入6条数据到A表,3条数据到B表.语句如下: create table A( ID ,) not null, AName ) null ) create table B( ...

  9. java基础:子类-父类构造器关系

    前提:父类:Parent.java 构造:默认构造方法(无参).带参数构造方法(并存时,需要显示创建无参构造方法) 例如:public Parent(){}.public Parent(String ...

  10. new 和 newInstance 的区别

    初始化一个类,生成一个实例的时候:newInstance() 和 new 有什么区别? 用newInstance与用new是区别的,区别在于创建对象的方式不一样,前者是使用类加载机制,那么为什么会有两 ...