关于Python 迭代器和生成器 装饰器
Python 简介
Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。
Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。
Python 是一种解释型语言: 这意味着开发过程中没有了编译这个环节。类似于PHP和Perl语言。
Python 是交互式语言: 这意味着,您可以在一个 Python 提示符 >>> 后直接执行代码。
Python 是面向对象语言: 这意味着Python支持面向对象的风格或代码封装在对象的编程技术。
Python 是初学者的语言:Python 对初级程序员而言,是一种伟大的语言,它支持广泛的应用程序开发,从简单的文字处理到 WWW 浏览器再到游戏
一、什么是迭代器协议
1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个stoplteration异常,以终止迭代(只能 往后走,不能往前退)
2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)
3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象
可迭代对象
可迭代对象泛指一类对象,不是指的每一种对象,确切的说满足以下的条件的对象可以成为可迭代对象:
1. 对象实现了__iter__方法
2. __iter__方法返回了一个迭代器对象
我们比较容易理解的可迭代对象,比如说可以用for语句去遍历,实际for语句的内部实现应该就是首先调用对象的__iter__方法,获取一个迭代器对象,接着不停的调用迭代器对象的__next__方法,循环遍历取值。
迭代器对象(迭代器)
迭代器协议包括这些条件:
1.对象实现了__next__方法
2.__next__方法返回了某个数值(当然一般情况下,我们需要的是返回这个对象的特定的数字,并且按照一定的顺序进行依次返回)
3.__next__方法需要在值取完的时候,抛出StopIteration的错误信息。
总结:
可迭代对象是 调用对象的__iter__方法能够返回迭代器对象的一种对象。
迭代器对象是实现了迭代器协议的对象。
二、什么是生成器?
可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己的内置的__iter__方法),所以生成器就是可迭代对象
1.生成器函数:常规函数的定义,但是,使用yield语句而不是return语句返回结果。yield语句语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行
2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
为何使用生成器之生成器的特点
Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生产层器的主要好处。
生成器小结:
a.是可迭代对象
b.实现了延迟计算,省内存
c.生成器本质和其他的数据类型一样,都是实现了迭代器协议,只不过生成器附加了一个延迟计算省内存的好处
三、装饰器
1、装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象,装饰器的本质是函数,主要用来装饰其他函数,也就是为其他函数添加附加功能
2、装饰器的原则:
(1) 装饰器不能修改被装饰的函数的源代码
(2) 装饰器不能修改被装饰的函数的调用方式
1)装饰器的原型:
import time
def showtime(func):
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print('spend is {}'.format(end_time - start_time)) return wrapper def foo(): #原函数不可以改变
print('foo..')
time.sleep(3) foo = showtime(foo) #
foo()
2)不带参数的装饰器:(装饰器,被装饰函数都不带参数)
import time
def showtime(func):
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print('spend is {}'.format(end_time - start_time)) return wrapper @showtime #foo = showtime(foo)
def foo():
print('foo..')
time.sleep(3) @showtime #doo = showtime(doo)
def doo():
print('doo..')
time.sleep(2) foo()
doo()
语法:@
装饰器便捷方法在 函数体上方写@showtime 与 foo = showtime(foo)相同
(3)带参数的被装饰的函数
import time
def showtime(func):
def wrapper(a, b):
start_time = time.time()
func(a,b)
end_time = time.time()
print('spend is {}'.format(end_time - start_time)) return wrapper @showtime #add = showtime(add)
def add(a, b):
print(a+b)
time.sleep(1) @showtime #sub = showtime(sub)
def sub(a,b):
print(a-b)
time.sleep(1) add(5,4)
sub(3,2)
(4)带参数的装饰器(装饰函数),
import time
def time_logger(flag = 0):
def showtime(func):
def wrapper(a, b):
start_time = time.time()
func(a,b)
end_time = time.time()
print('spend is {}'.format(end_time - start_time)) if flag:
print('将此操作保留至日志') return wrapper return showtime @time_logger(2) #得到闭包函数showtime,add = showtime(add)
def add(a, b):
print(a+b)
time.sleep(1) add(3,4)
(5)装饰器语法总结
def myDecorator(...): #定义装饰器,可能带参数
def decorator(func): #装饰器核心,以被装饰的函数对象为参数,返回装饰后的函数对象
def wrapper(*args, **kvargs): #装饰的过程,参数列表适应不同参数的函数
... #修改函数调用前的行为
func(*args, **kvargs) #调用函数
... #修改函数调用后的行为
return wrapper
return decorator @myDecorator(...): #给函数加上装饰器
def myFunc(...): #自己定义的功能函数
...
Python内置装饰器
在Python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod 和property。
staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用
classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)
property 是属性的意思,表示可以通过通过类实例直接访问的信息
import time
class Foo(object):
def __init__(self, func):
self._func = func def __call__(self):
start_time = time.time()
self._func()
end_time = time.time()
print('spend is {}'.format(end_time - start_time)) @Foo #bar = Foo(bar)
def bar():
print('bar..')
time.sleep(2) bar()
最新文章
- Eclipse无法启动错误之Ensure that the org.eclipse.core.runtime bundle is resolved and started (see config.ini)
- uart串口的调试学习
- Android之Handler用法总结(1)
- ZSDRM001-发货清单
- Part 17 Temporary tables in SQL Server
- spring3+struts2+hibernate3整合出现的问题,No mapping found for dependency [type=java.lang.String, name='struts.objectFactory.spring.enableAopSupport']
- ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
- Lucene学习笔记: 四,Lucene索引过程分析
- Codeforces Round #321 (Div. 2) A. Kefa and First Steps 水题
- Ubuntu自己主动搭建VPN Server - PPTP的Shell脚本
- Fragmen和Activity之间的通信--接口和实现的分离(转)
- 【PHP】最详细PHP从入门到精通(三)——PHP中的数组
- Java设计模式(五)Prototype原型模式
- ConfirmCancelBottomSheetDialog【确认取消底部对话框】
- docker 安装 hbase安装 java连接hbase (mac环境)
- CSS制作环形进度条
- selenium + firefox驱动版本对应。
- nginx的ngx_http_realip_module模块和http头X-Forwarded-For、X-Real-IP
- Bootstrap的aria-label和aria-labelledby
- MySQL连接查询(多表查询)
热门文章
- 使用Jmeter进行压力测试结果偏差较大原因分析
- 《深入理解 Java 虚拟机》读书笔记:早期(编译期)优化
- Journal of Proteome Research | 人类牙槽骨蛋白的蛋白质组学和n端分析:改进的蛋白质提取方法和LysargiNase消化策略增加了蛋白质组的覆盖率和缺失蛋白的识别 | (解读人:卜繁宇)
- 关于PS切图
- dijkstra模板题 洛谷1339 邻接图建边
- 试译 Understanding Delta-Sigma Modulators
- 基于Modbus三种CRC16校验方法的性能对比
- 「面试指南」解读JavaScript原始数据类型
- jq 导航跟随 模拟京东手机端
- [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem