Python学习第二阶段,day1, 装饰器,生成器,迭代器
装饰器
不得不说,这是对初学者最难以理解的概念了,虽然我学过面向对象,但还是被搞懵逼了。。前面还好理解,主要是后面“装饰器的装饰器”我理解不了。装饰器工厂,根据传入的参数不同去返回不同的装饰器,我不得不在网上查了很多资料去弄懂它,如果没搞清楚这个概念,我是没法安安心心往下学的~~
这里特别要感谢刘志军的这篇文章,完美的解决了我的疑惑:
https://zhuanlan.zhihu.com/p/27449649
装饰器可以在不修改源代码,和原调用方式的基础上,给原有函数增加功能。当然,可以增加功能,只能在原有函数的前面或者后面增加功能,但是没办法改变原有函数的逻辑。要实现一个装饰器,要先掌握几个基本的概念:
1.函数也是一种“变量” 2.高阶函数 3.嵌套函数 4,闭包。
1.函数也是一种“变量”如何理解?
例如,def sayhi()
print ("hello,everyone!")
如果打印sayhi,就是0x0000000001ECE730,一个内存地址。
如果调用sayhi(),内存地址后面加个括号就调用这个函数。
函数定义,把函数体当成字符串存放在内存中,用函数名指向它,调用之前,并不会管函数体是什么内容

2.高阶函数。把一个函数名当做参数传给另一个函数,或者返回值中包含函数名
def dec(func):
print("in decorator")
func()
函数名作为参数传给函数
3,引用计数。
Python内存回收机制,当没有变量名指向某个常量时,即改常量引用计数为0,Python就回收该常量,函数也是一样,没有函数名指向它,或者程序结束就回收该函数体内容
匿名函数 lambda x : x*3 没有函数名指向它,如果给它赋值,calc = lambda x:x*3 就不会马上回收
4.嵌套函数。在函数里定义一个新函数,并返回新函数
def dec(func):
def wrapper(*args, **kwargs):
# 原函数前面增加功能
res = func(*args, **kwargs)
# 原函数后面增加功能
return res
return wrapper
这就是个装饰器decorator,在被装饰函数前面加上:func = dec(func)
改成方便的语法糖写法:@dec
5 .闭包closure
def closure(str):
def decrator(func):
def wrapper():
....
if (str)
func()
else
....
....
return wrapper
return decrator
@closure(str='1') 相当于 func = closure('1')(func)
@closure(str='2') 相当于 func = closure('2')(func)
把参数给了装饰器,可以生产各种类型的装饰器。。根据传的值str判断
生成器
列表生成式:gen = [i for i in range(10)] 生成一个list 名为gen = [0 , 1, 2, 3, 4, 5, 6, 7, 8, 9]这个列表已经保存在内存中,可以根据下标访问其中任意一个元素。
想一下,如果元素有几百万个,是不是都要全部在内存中放着准备取用呢?而且可能并不会用到第几百万个元素,该如何解决内存问题呢??
这时候生成器generator就产生了:
在上面列表生成式方括号改为圆括号变成一个生成器 gen = (i for i in range(10))
这时候gen = generator object <genexpr> at 0x0000000001DF87D8变成了一个地址。当然也就无法通过下标去访问某个元素了。
要访问某个元素就只能通过gen.next()方法去访问。访问一个生成一个。直到出现你想访问的元素。把上面的列表生产式改写一下,换一种写法:
def gen(i):
"i表示长度,而且每次取数据都是从1开始循环,从1取到i,yield返回n并记录该中断点"
n = 1
while n <= i:
yield n
n += 1
return "done-----" genner = gen(10) # 第一种调用生成器的方式,用whil true + next
while True: # 循环到第10个以后就不能next了,因为跳出了while循环yield不了,就抛异常StopIteration
try:
print(genner.__next__())
except StopIteration as e:
print(e.value)
break # 第二种调用生成器的方式,用for循环,这里看出gen(10)是一个迭代器了
for i in gen(10):
print(i)
是不是可以认为,生成器用for循环的方式去访问,就叫做“迭代器”??????
注意:生成器的牛逼之处在于yield关键字,你定义的时候就指明了这个生成器的长度。后面每次next()都是接着上一个netx()的后面。所以可以在next()中间做其他事情,因为不会影响结果。
还可以利用send()给yield关键字传值并激活yield, next()只能激活yield
生成器的并行计算:
'''
简单的消费者生产者模型,又是一个简单的协程。 send(a)的作用是将a的值传给yield,并且激活yield。而next()的作用只是激活yield。 消费者模型中,有Alex和Lee两个消费者,吃包子的过程实际上是顺序执行的,只是计算机的速度太快 如果把他们分开显示,可以看成是同步发生的,这就是一个简单的协程
''' import time def consummer(name):
print("%s,准备开始吃包子了!!" % name)
while True:
baozi = yield
print("包子%s 来了,被%s 吃了!" %(baozi, name)) def producer(name):
c1 = consummer("Alex")
c2 = consummer("Lee")
c1.__next__()
c2.__next__()
for i in range(6):
time.sleep(1)
print("%s 做了包子%s分两半。。。。。。。。" %(name, i))
c1.send(i)
c2.send(i) producer("bob")
------------------------------执行结果-------------------------------------
Alex,准备开始吃包子了!!
Lee,准备开始吃包子了!!
bob 做了包子0分两半。。。。。。。。
包子0 来了,被Alex 吃了!
包子0 来了,被Lee 吃了!
bob 做了包子1分两半。。。。。。。。
包子1 来了,被Alex 吃了!
包子1 来了,被Lee 吃了!
bob 做了包子2分两半。。。。。。。。
包子2 来了,被Alex 吃了!
包子2 来了,被Lee 吃了!
bob 做了包子3分两半。。。。。。。。
包子3 来了,被Alex 吃了!
包子3 来了,被Lee 吃了!
bob 做了包子4分两半。。。。。。。。
包子4 来了,被Alex 吃了!
包子4 来了,被Lee 吃了!
bob 做了包子5分两半。。。。。。。。
包子5 来了,被Alex 吃了!
包子5 来了,被Lee 吃了!
迭代器
1可迭代对象(Iterable): 可直接作用于for循环的对象统称为Iterable可迭代对象,例如 list tuple dict set str 等,判断方法 isinstance(xxx, Iterable)
2.迭代器(Iterator):可以被next()函数调用并不断返回下一个值的对象,它们表示一个惰性的计算序列,可以看出:生成器一定是迭代器,而迭代器不一定是生成器 判断方法: isinstance(xxx,Iterator)
3.Iterable变为Iterator: iter()方法
from collections import Iterator, Iterable def gen(i):
"i表示长度,而且每次取数据都是从1开始循环,从1取到i,yield返回n并记录该中断点"
n = 1
while n <= i:
yield n
n += 1
return "done-----" genner = gen(10)
list1 = [5,2,3,4,5,6,9] print(isinstance(genner, Iterator)) # 判断是否为迭代器
print(isinstance(genner,Iterable)) # 判断是否为可迭代对象
lst = iter(list1) # 用iter()方法把list1变成迭代器
print(lst.__next__()) # 打印结果5
为什么list dict str 等不是迭代器???
因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被netx()函数调用并不断返回下一个数据,知道没有数据时抛出StopIteration错误。
可以把数据流看成一个有序序列,但不知道序列的长度,只能不断通过netx()按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要下一个数据时才计算
Iterator甚至可以表示一个无限大的数据流,如全体自然数。而list是永远不可能存储全体自然数的。
Python学习第二阶段,day1, 装饰器,生成器,迭代器的更多相关文章
- Python自动化 【第四篇】:Python基础-装饰器 生成器 迭代器 Json & pickle
目录: 装饰器 生成器 迭代器 Json & pickle 数据序列化 软件目录结构规范 1. Python装饰器 装饰器:本质是函数,(功能是装饰其它函数)就是为其他函数添加附加功能 原则: ...
- python学习之day5,装饰器,生成器,迭代器,json,pickle
1.装饰器 import os import time def auth(type): def timeer(func): def inner(*args,**kwargs): start = tim ...
- 跟着ALEX 学python day4集合 装饰器 生成器 迭代器 json序列化
文档内容学习于 http://www.cnblogs.com/xiaozhiqi/ 装饰器 : 定义: 装饰器 本质是函数,功能是装饰其他函数,就是为其他函数添加附加功能. 原则: 1.不能修改被装 ...
- Python(四)装饰器、迭代器&生成器、re正则表达式、字符串格式化
本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解 ...
- python基础-函数之装饰器、迭代器与生成器
1. 函数嵌套 1.1 函数嵌套调用 函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数 def bar(): print("from in the bar.") def f ...
- python三大器(装饰器/生成器/迭代器)
1装饰器 1.1基本结构 def 外层函数(参数): def 内层函数(*args,**kwargs); return 参数(*args,**kwargs) return 内层函数 @外层函数 def ...
- Python三大神器:装饰器,迭代器,生成器
一.装饰器 由于一个函数能实现一种功能,现在想要在不改变其代码的情况下,让这个函数进化一下,即能保持原来的功能,还能有新的"技能",怎么办? 现已经存在一个自定义的函数func1, ...
- python学习笔记(五):装饰器、生成器、内置函数、json
一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...
- python学习笔记之装饰器、生成器、内置函数、json(五)
一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里面 ...
- python第四周:装饰器、迭代器、内置方法、数据序列化
1.装饰器 定义:本质是一个函数,(装饰其他函数)就是为其他函数添加附加功能 原则:不能修改被装饰函数的源代码,不能修改被装饰函数的调用方式 实现装饰器的知识储备: 函数即“变量”.每当定义一个函数时 ...
随机推荐
- SQLALchemy之介绍,基本使用
一.介绍 SQLALchemy也是一个python的ORM框架,django内部的ORM框架只适用于django,而SQLALchemy适用于所有python的web框架 SQLAlchemy是一个基 ...
- POJ2069 最小球覆盖 几何法和退火法
对这种问题不熟悉的读者 可以先去看一看最小圆覆盖的问题 ZOJ1450 现在我们来看最小球覆盖问题POJ2069 题目很裸,给30个点 求能覆盖所有点的最小球的半径. 先给出以下几个事实: 1.对于一 ...
- Mysql建表出现1005错误
转自:http://blog.sina.com.cn/s/blog_757807f30100vz23.html 当在创建一个表时提示1005错误无法创建时,注意检查一下几点: 1.当此表有外键时,检查 ...
- 14_传智播客iOS视频教程_OC的数据类型
对比一下OC和C差别,首先第一个是数据类型. C语言的数据类型分哪几类?C语言有哪些数据类型? 基本数据类型当然还包括int的一些修饰符.像short.long.long long.unsigned. ...
- C# 简单实现直线方程,抛物线方程(转载)
http://www.cnblogs.com/hsiang/archive/2017/01/17/6294864.html 本例子是简单的在WinForm程序中实现在坐标系中绘制直线方程,抛物线方程, ...
- 洛谷P4158 [SCOI2009]粉刷匠
传送门 设$dp[i][j][k][0/1]$表示在涂点$(i,j)$,涂了$k$次,当前点的颜色是否对,最多能刷对多少个格子 首先换行的时候肯定得多刷一次 然后是如果和前一个格子颜色相同,那么当前点 ...
- lodop 打印
使用Lodop打印: 一.在官网下载http://www.lodop.net/download.html 若是安装还是提示未安装,就按转这个 二.准备两个js 三.需要在页面最上面加入 <htm ...
- Java实现日期时间对象的使用
利用类对象计算日期 在利用Java语言进行信息系统开发中,经常需要对日期进行计算和转换,比如,设置了某活动的开始日期和结束日期,系统需要判断当前是否是该活动时间,在Java开发的信息系统中,通常日期以 ...
- C#方法的一些规则
C# 方法 一个方法是把一些相关的语句组织在一起,用来执行一个任务的语句块.每一个 C# 程序至少有一个带有 Main 方法的类. 要使用一个方法,您需要: 定义方法 调用方法 下面是方法的各个元素: ...
- magento getUrl函数跳转admin模块问题
在用以下代码时,跳转后的url里面会是空的,即没有admin这个值 $this->getUrl('admin/catalog_product/edit', array('id' => $c ...