一、迭代器

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

可迭代对象:遵循迭代协议的对象就是可迭代对象。

迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

迭代器有两个基本的方法:iter() 和 next()

字符串,列表或元组对象都可用于创建迭代器,生成迭代器的方法是iter():

 li = [1,2,3,4]
#inter()本质调用了内置的__iter__
a = li.__iter__() #生产一个可迭代对象
#next()本质调用__next__()
a.__next__() #对可迭代对象进行取值

方法二:

>>li = [1,2,3,4,5]
>>it = iter(li) #生成一个迭代器
>>it.__next__()
1
>>next(it) #以上两种next都可以使用
2
>>for i in it:
print(i)
3
4
5
#迭代完毕后,迭代器里面的数据就没有了
>> type(it)
<class 'list_iterator'> #类型是迭代器类型

二、生成器

在描述生成器前我们先来了解列表生成式:

#普通定义的列表直接把列表写死
li = [1,2,3,4,5] #使用列表生成式,可以为列表添加一些新的属性 li1 = [a*a for a in range(10)]
print(li1) #也可以用以下两种方法方法 li2 = list(map(lambda x:x+1,li))
print(li2) a = []
for i in range(10):
a.append(i+1)
print(a) #从以上对比可以看出,使用第二种方法代码最为简单,即列表生成式

  虽然有列表生成式,可以简化生成特定列表的操作,但是当列表数据过大,就会过度的消耗内存,并且列表是数据也不会一直使用,在python中有一种一边循环一边计算的机制就是生成器。

生成器的第一种表现形式:

#创建一个生成器

li = (a*a for a in range(10))

print(li) #<generator object <genexpr> at 0x00000000027BD468>,返回一个生成器对象,用next调用对象
print(li.__next__())
print(next(li)) #且只能调用一次,不能往回调用 '''我们讲过,generator保存的是算法,每次调用next(g),
就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,
抛出StopIteration的错误。一般情况下,我们用for循环来调用全部数据''' for i in li:
print(i)

生成器的第二种表现形式:

  生成器:一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。调用一个生成器函数,返回的是一个迭代器对象。

  yield语法:每当行数运行到yield是就会中断并且保存当前所有的运行信息,并且在执行next()方法后继续从中断的地方运行。

#生成一个斐波拉契数列
def fib(max):
a,b,n = 0,0,1
while n < max:
a, b = b,a+b
n +=1
return 'done' c = fib(5)
print(c)
#弊端,会直接全部生成 #把该函数变为一个生成器
def fib2(max):
a,b,n = 0,0,1
while n < max:
yield b #遇到一次返回一次,再次激活则运行后面的代码,用next激活
a, b = b,a+b
n +=1 d = fib2(5)
print(next(d))

下面是一个利用yield实现的一种单线程下的并发效果,也可以理解为一协程(后面会讲这一内容):

import time

def consumer(name):
print('%s准备吃包子了!' % name)
while True:
baozi = yield # 保存当前状态的值,并且退出函数
print('包子[%s]来了,被[%s]吃了!'% (baozi,name)) # c = consumer('alix') 生成一个生成器对象
# c.__next__() 调用生成器 def producer():
c = consumer('a')
c2 = consumer('b')
c.__next__()
c2.__next__()
print('老子开始准备做包子了')
for i in range(10):
time.sleep(1)
print('做了1个包子,分两半')
c.send(i) #给yield传值,并且唤醒yield
c2.send(i)
producer()

三、装饰器

装饰器:本质上就是函数,作用就是为其他函数添加其他功能
原则:1、不能修改被装饰的函数的源代码
2、不能修改被修饰函数的调用方式

在将装饰器前我们进行一些装饰器的知识储备:

1.函数即'变量'
2.高阶函数
1.把一个函数名当做实参传给另一个函数(添加功能不修改函数的源代码)
2.返回值中包含函数名(不修改函数的调用方式)
3.嵌套函数

函数即“变量”:

函数定义好后就像变量一样存储在内存中,当我们去调用的时候才会有意义。

#函数即变量

# def foo():
# print('in the foo')
# foo() #即无需考虑函数的定义顺序,就和定义变量一样 def bar():
print('in the bar')
def foo():
print('in the foo')
bar()
foo()

高阶函数:即把一个函数名当做实参传递给函数,就类似有把一个变量名传递给函数。

# 高阶函数:把一个函数名,当做实参传给函数
import time
def bar():
time.sleep(3) #暂停3秒
print('in the bar') def text1(fun):
start_time = time.time() #起始时间
fun()
stop_time = time.time() #结束时间
print('the fun time is %s' % (stop_time-start_time)) #计算出fun()所用的时间 text1(bar) #将该函数名传递进去 def bar2():
time.sleep(3)
print('in the bar2') def text2(fun):
print(fun)
return fun bar2 = text2(bar2)
bar2()

通过高阶函数的作用可以看出:在不改变函数的源代码的情况下,给函数增加了计时的功能

嵌套函数:

def foo():
print('in the foo')
def bar():
print('in the bar')
bar()
foo()

结合以上三种实现装饰器:

import time
def timer(func): #timer(text1) func=text1 装饰器函数
def wrapper(*args,**kwargs):
start_time = time.time()
func() #run text1
stop_time = time.time()
print('the fun run time is %s' % (stop_time-start_time))
return wrapper @timer # text1 = timer(text1) 这一步就是把text1传入timer
def text1():
time.sleep(1)
print('the is text1') text1()

带参数的装饰器:

user,passwd = 'alex',''

def auth(outh_type):
print('auth func:',outh_type)
def outh_wrapper(func):
def wrapper(*args,**kwargs):
print('wrapper func args:',*args,**kwargs)
if outh_type == 'local':
username = input('Username:'.strip())
password = input('Password:'.strip())
if user == username and passwd == password:
print('\033[32;1mUser has passed authentication\033[0m')
res = func(*args,*kwargs)
print('-- after authentication')
return res
else:
exit("\033[31;1mInvalid username or password\033[0m")
elif outh_type == 'ldap':
print('搞毛线') return wrapper
return outh_wrapper @auth(outh_type='local')
def index():
print('welcom to index page') index()

http://www.cnblogs.com/wupeiqi/articles/4980620.html

Python 全栈开发五 迭代器 生成器 装饰器的更多相关文章

  1. 巨蟒python全栈开发-第15天 装饰器

    一.今日内容总览 关于函数的装饰器1.装饰器(重点,难点)(要求:反复写,代码不多但是很绕) 开闭原则:(比如,菜单是拆散的,一点点搞的,用友拆散自己的功能,以后就不用开发了) (1)对功能的扩展开放 ...

  2. python全栈开发day21-2 几个装饰器总结

    1 @property 将一个方法伪装成属性 2.@propertty @f.setter 设置伪装成方法的属性 3.@propertty @f.deleter 删除一个伪装成方法的属性. class ...

  3. Python全栈之路----函数进阶----装饰器

    Python之路,Day4 - Python基础4 (new版) 装饰器 user_status = False #用户登录后改为True def login(func): #传入想调用的函数名 de ...

  4. Python全栈开发之8、装饰器详解

    一文让你彻底明白Python装饰器原理,从此面试工作再也不怕了.转载请注明出处http://www.cnblogs.com/Wxtrkbc/p/5486253.html 一.装饰器 装饰器可以使函数执 ...

  5. Python全栈day28(类的装饰器)

    类是一个对象也可以像函数一样加装饰器 类的装饰器.py def deco(obj): print('======',obj) obj.x=1 obj.y=2 obj.z=3 return obj # ...

  6. python全栈开发-Day11 迭代器、生成器、面向过程编程

    一. 迭代器 一 .迭代的概念 迭代器即迭代的工具,那什么是迭代呢? 迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值 while True: #只是单纯地重复,因而 ...

  7. Python全栈开发之---迭代器、可迭代对象、生成器

    1.什么叫迭代 现在,我们已经获得了一个新线索,有一个叫做“可迭代的”概念. 首先,我们从报错来分析,好像之所以1234不可以for循环,是因为它不可迭代.那么如果“可迭代”,就应该可以被for循环了 ...

  8. python全栈开发_day13_迭代器和生成器

    一:迭代器 1)可迭代对象 具有内置函数__iter__的数据就是可迭代对象 2)迭代器对象 具有内置函数__next__的数据就是迭代器对象 迭代器对象一定是可迭代对象,可迭代对象不一定是迭代器对象 ...

  9. python全栈开发学习_内容目录及链接

    python全栈开发学习_day1_计算机五大组成部分及操作系统 python全栈开发学习_day2_语言种类及变量 python全栈开发_day3_数据类型,输入输出及运算符 python全栈开发_ ...

随机推荐

  1. 装饰模式和它在JDK中的实现

    对装饰者模式的一个通俗的理解就是:一个东西A包装了另外一个东西B,A在B的功能基础上又扩展了新的功能,但是对外提供的接口不变 装饰者模式(Decorator)的定义: 动态地给一个对象添加一些额外的职 ...

  2. Git版本控制工具的简单使用

    1.下载gitd客户端,注册github账号. 2.本地生成公钥和私钥,并将公钥粘贴到github上,测试连接. 3.先pull,从远程服务器中下载项目文件,然后再pushi,提交至服务器. 4. g ...

  3. linux下的文件解压命令

    说一下tar命令的参数含义:z,使用gzip解压,x:extract解压,v:显示详细信息,f:使用归档在当前文件夹. 在解压时出现了解压失败,原因是没有sudo,无法创建文件夹.

  4. WPF使用Canvas绘制可变矩形

    1.问题以及解决办法 最近因为项目需要,需要实现一个位置校对的功能,大致的需求如下:有一个图片,有一些位置信息,但是位置信息可能和实际有些偏差,需要做简单调整,后面会对这张图片进行切割等,做些处理.( ...

  5. nginx启用TCP反向代理日志配置

    Nginx使用TCP反向代理日志配置不同于http 修改nginx配置文档/usr/local/nginx/conf/nginx.conf 设置日志格式 stream { log_format pro ...

  6. db2 基础语法

    一.db2 基础 基本语法 注释:“--”(两个减号) 字符串连接:“||” 如set msg=’aaaa’||’bbbb’,则msg为’aaaabbbb’ 字符串的引用:‘’(一定用单引号),如果需 ...

  7. SQL中的Continue和Break

    x 在Sql Server中,sql语句包含While循环的时候,肯定都或多或少的用到Continue和Break... 下面撸了一个小Demo , Begin ),@Index) Begin Pri ...

  8. 关于servelet入门介绍

    servelet 容器 将前台的请求转发给后台        接受 http 表单, 后台处理操作数据库并且放回用户 .(粗劣) 手工编写第一个Servlet 1, 继承httpservlet 2, ...

  9. shell脚本的基本结构以及如何执行

    1.shell脚本通常以.sh为后缀,不是说不带这个.sh脚本就不会执行,而是大家一种通用的命名规范而已 2.shell脚本中的第一行一定是:#! /bin/bash.该命令说明,该文件使用的是bas ...

  10. css中display:inline-block display:-moz-inline-box display:-moz-inline-stack 的区别

    很多时候我们必须使一些块元素并排显示,一般想到的是必须使用浮动,但是块元素浮动给边距(margin)的时候在IE下会出现加倍的BUG,所以很多时候不得不把这个块元素套在一个内联元素里面,然后给内联元素 ...