1 迭代器

这里我们先来回顾一下什么是可迭代对象(Iterable)

可以直接作用于for循环的对象统称为可迭代对象,即Iterable。
  # 一是集合数据类型,如list、tuple、dict、set、str等;
  # 二是generator,包括生成器和带yield的generator function。

那么什么又是迭代器(Iterator)?

可以被next()函数调用不断返回下一个值(直到没有数据时抛出StopIteration错误)的对象称为迭代器,即Iterator。

 import collections
print(isinstance([], collections.Iterable)) # True
print(isinstance(iter([]), collections.Iterator)) # True
print(isinstance(iter([]), collections.Iterable)) # True
print(isinstance([], collections.Iterator)) # False
print(isinstance((x * x for x in range(10)), collections.Iterable))
# isinstance() 是python内建函数,返回对象是否是类或其子类的实例。若是,返回True,反之返回False。
# Iterable 英文是‘可迭代的’,形容词;Iterator英文是‘迭代器’,名词。 # 那么当 isinstance()的第二个参数是collections.Iterable时,是判断第一个参数是不是Iterable对象(可迭代对象)
# 当 isinstance()的第二个参数是collections.Iterator时,是判断第一个参数是不是Iterator对象(迭代器对象) # 那么什么是可迭代对象?可以直接作用于for循环的对象统称为可迭代对象,即Iterable。
# 一是集合数据类型,如list、tuple、dict、set、str等;
# 二是generator,包括生成器和带yield的generator function。 # 是么是迭代器?可以被next()函数调用并不断返回下一个值(直到没有数据时抛出StopIteration错误)的对象称为迭代器:Iterator。 # 你可能会问,为什么list、dict、str等数据类型不是Iterator?
# 这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。
# 可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,
# 所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
# Iterable 可以通过iter()函数转换得到 Iterator,但Iterable不一定是Iterator;而Iterator可以直接作用于for循环,所以Iterator是Iterable。

2 生成器

首先先理清几个概念:

  generator : A function which returns a generator iterator. It looks like a normal function except that it contains yield expressions for producing a series of values usable in a for-loop or that can be retrieved one at a time with the next() function.

  generator iterator : An object created by a generator funcion.

  generator expression : An expression that returns an iterator.

可见,我们常说的生成器,就是带有 yield 的函数,而 generator iterator 则是 generator function 的返回值,即一个 generator 对象;

形如 (elem for elem in [1, 2, 3]) 的表达式,称为 generator expression ,实际使用与 generator 无异。

  Python’s generators provide a convenient way to implement the iterator protocol.

  也就是说: generator 就是 iterator 的一种,以更优雅的方式实现的 iterator 。我们来一个例子:

 from collections import Iterable
from collections import Iterator
from collections import Generator def odd():
print('step 1')
yield 1
print('step 2')
yield(3)
print('step 3')
yield(5) ge = odd()
print(isinstance(ge, Iterator))
print(isinstance(ge, Iterable))
print(isinstance(ge, Generator))
print(type(ge))
# 结果
# True
# True
# True
# <class 'generator'>

这也充分印证了上面的说法,generator就是一种iterator。而且Gennerator这个类是继承了Iterator的。

3 装饰器

什么是装饰器(Decorator)?

  本质上:是一个返回函数的高阶函数。

生产上,什么时候用装饰器?

  当我们想要给一个函数func()增加某些功能,但又不希望修改func()函数的源代码的时候就需要用装饰器了。(在代码运行期间动态增加功能)

假如,你有一个网站,之前是免费开放的,谁都可以访问。但是有一天你不想免费开放了,你想让大家必须登陆后才能访问,但是呢,网站已经上线了,一直是跑着的,不能修改源码。这个时候就要用这个装饰器了。

前奏:

假设你原先的网站首页是这个函数:

def home():
print("欢迎来到XX首页!") home()

首先我们必须得明白:函数也是一个对象(python里一切皆对象),且可以赋值给其他变量。例如:

def home():
print("欢迎来到XX首页!") f = home
f()

这和直接调用home()结果是一样的。

那么怎么做到,不改变home的源码给它加上添加登录功能呢?看下面的代码,注意其中的讲解:

 def login(func):
"""
在这里从新定义一个高阶函数,
这就是decorator。
我们一会儿会仔细分析。
"""
def wrapper(*args, **kwargs):
user = "zingp" # 假设这是数据库中的用户名和密码
passwd = ""
username = input("输入用户名:")
password = input("输入密码:")
if username == user and password == passwd:
return func(*args, **kwargs)
else:
print("用户名或密码错误。")
return wrapper @login # 利用python的@语法,把decorator置于home函数的定义处 相当于home = login(home)
def home():
print("欢迎来到XX首页!") home()

运行看看,是不是没改变home源码和home的调用方式,给home添加了登录验证的功能?

其实,这里@login相当于做一这么一件事:home = login(home)

那么当执行23行时就是这样的:login(home)()

  login(home)是什么?他就是调用login这个函数后的返回值,即wrapper

此时,login(home)()即变成了 wrapper()

  执行wrapper() ,返回home()函数并执行home()

整个过程就是这样。

但是这里还有个问题,就是当没加装饰器的时候print(home.__name__)得到的函数名是home,加了装饰器后print(home.__name__)得到的结果就是wrapper了。

我们虽然没有改home函数的源代码,但是更改了__name__属性,所以,最美好的结果是连属性也不更改吧?

你可能想写个wrapper.__name__ = func.__name__这样的代码,就可以了嘛。但是呢,Python内置的functools.wraps就是专门干这个事的。

请看完整的装饰器代码

 import functools  # 先得导入这个工具

 def login(func):

     @functools.wraps(func)
def wrapper(*args, **kw):
user = "zingp" # 假设这是数据库中的用户名和密码
passwd = ""
username = input("输入用户名:")
password = input("输入密码:")
if username == user and password == passwd:
return func(*args, **kw)
else:
print("用户名或密码错误。")
return wrapper @login
def home():
print("欢迎来到XX首页!") home()
print(home.__name__)

现在是不是属性也没改了?

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

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

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

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

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

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

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

  4. Python迭代器,生成器,装饰器

    迭代器 通常来讲从一个对象中依次取出数据,这个过程叫做遍历,这个手段称为迭代(重复执行某一段代码块,并将每一次迭代得到的结果作为下一次迭代的初始值). 可迭代对象(iterable):是指该对象可以被 ...

  5. Python(迭代器 生成器 装饰器 递归 斐波那契数列)

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

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

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

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

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

  8. Day04 - Python 迭代器、装饰器、软件开发规范

    1. 列表生成式 实现对列表中每个数值都加一 第一种,使用for循环,取列表中的值,值加一后,添加到一空列表中,并将新列表赋值给原列表 >>> a = [0, 1, 2, 3, 4, ...

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

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

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

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

随机推荐

  1. 跨终端Web

    1.终端vs设备 H5页面运行在同一设备的不同终端下. (1)Web浏览器. (2)微信.QQ浏览器. (3)移动App的Webview. (4)TV机顶盒. 2.跨终端的实现方式 (1)响应式 存在 ...

  2. [ACM_模拟] UVA 12504 Updating a Dictionary [字符串处理 字典增加、减少、改变问题]

      Updating a Dictionary  In this problem, a dictionary is collection of key-value pairs, where keys ...

  3. Checkpoint--实现步骤

    Checkpoint 实现步骤: 1.将CheckPoint标记写入日志(标记中包含当前数据库中活动的事务信息),并将Log Block写入持久化存储 2.将Buffer Pool中所有的脏页写入磁盘 ...

  4. 基于MVC框架layui分页控件实现前端分页信息写法

    详细链接:https://shop499704308.taobao.com/?spm=a1z38n.10677092.card.11.594c1debsAGeak@{ ViewBag.Title = ...

  5. Mac OS 10.12 - Gogland和在Windows中使用的不同!!

    刚刚在Mac OS 10.12用Gogland写了一个小小的GO语言测试程序,经过一番尝试才算把Gogland配置好,写出这个测试程序!Gogland在Mac OS 10.12里和Windows里面确 ...

  6. es6中箭头函数 注意点

    var aaabbb = 'kkkooo' setTimeout(()=>{ var aaaa = 'kkkk'; console.log(this) },1000); 因为据我了解,箭头函数指 ...

  7. 本机的虚拟机执行ifconfig,显示不出ip的解决方法

    源于:https://blog.csdn.net/fuweihua123/article/details/78423715?locationNum=4&fps=1 本机的虚拟机执行ifconf ...

  8. linux,软链接配置node,npm全局命令

    sudo ln -s /usr/local/bin/node   /bin/node sudo ln -s /usr/local/bin/npm    /bin/npm 这样配置后,在root下和别的 ...

  9. How to manage IntelliJ IDEA projects under Version Control Systems

    如何在版本控制系统中管理 IntelliJ IDEA 项目文件 IntelliJ IDEA 设置详细,功能强大.在实际工作中,我们有时会遇到跟同事共享项目文件的情况. 那么,有哪些项目文件应该加入到版 ...

  10. Storm系列三: Storm消息可靠性保障

    Storm系列三: Storm消息可靠性保障 在上一篇 Storm系列二: Storm拓扑设计 中我们已经设计了一个稍微复杂一点的拓扑. 而本篇就是在上一篇的基础上再做出一定的调整. 在这里先大概提一 ...