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. 20、docker swarm

      Swarm是Docker官方提供的一款集群管理工具,其主要作用是把若干台Docker主机抽象为一个整体,并且通过一个入口统一管理这些Docker主机上的各种Docker资源.Swarm和Kuber ...

  2. java中的static(包括类前面修饰的static、方法前面修饰的static、成员变量前面修饰的static)

    static是静态修饰符: 什么叫静态修饰符呢?大家都知道,在程序中任何变量或者代码都是在编译时由系统自动分配内存来存储的,而所谓静态就是指在编译后所分配的内存会一直存在,直到程序退出内存才会释放这个 ...

  3. Hyper-V启动虚拟机,消耗C盘大量磁盘空间

    问题描述 经常使用Hyper-V虚拟机的朋友,可能会碰到这样的现象,当启动某些虚拟机的是否,发现C盘的空间突然减少,减少的空间与虚拟机的内存一样大少. 通过分析C盘空间的磁盘文件,发现在Hyper-V ...

  4. linux系统编程之信号(八):三种时间结构及定时器setitimer()详解

    一,三种时间结构 time_t://seconds   struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microsecond ...

  5. C# 委托和事件,简单示例说明问题

    先看看示例效果 按照国际惯例,得先说说概念. 委托(C# 编程指南) 事件(C# 编程指南) 以上内容来自MSDN. 委托源码 [委托] 概念和代码都有了.剩下的就是应用了,要是只知道概念不会用,那还 ...

  6. Install Nginx on CentOS 7

    To set up the yum repository for RHEL/CentOS, create the file named /etc/yum.repos.d/nginx.repo with ...

  7. 构建NetCore应用框架之实战篇(四):BitAdminCore框架1.0登录功能细化及技术选型

    本篇承接上篇内容,如果你不小心点击进来,建议从第一篇开始完整阅读,文章内容继承性连贯性. 构建NetCore应用框架之实战篇系列 一.BitAdminCore框架1.0版本 1.1.0版本是指最小版本 ...

  8. 解决DbContext对象创建问题

    解决DbContext对象创建问题 方法一: 使用CallContext public class BaseController : Controller { public MyContext db ...

  9. 201621123023《Java程序设计》第5周学习总结

    一.本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 接口.interface.comparable.comparator 1.2 尝试使用思维导图将这些关键词组织起来.注:思维导图一 ...

  10. Django(app的概念、ORM介绍及编码错误问题)

    day61 Django中的APP:         什么是APP?以及为什么要用APP?                  project  --> 项目  (老男孩教育大学校)        ...