python——迭代器、生成器、装饰器

迭代器

迭代器规则

  迭代:重复做一些事很多次,就像在循环中那样。

  不仅可以对字典和序列进行迭代,还可以对其他对象进行迭代:只要该对象实现了__iter__方法。

  __iter__方法会返回一个迭代器(iterator),所谓的迭代器就是具有next方法(这个方法在调用时不需要任何参数)的对象。在调用next方法时,迭代器会返回他的下一个值。如果next方法被调用,但迭代器没有值可以返回,就会引发一个StopIteration异常。

  注意:迭代器规则在3.0中有一些变化。在新的规则中,迭代器对象应该实现__next__方法,而不是next。而新的内建函数next方法可以用于访问这个方法。换句话说,next(it)等同于3.0之前版本中的it.next()。

  迭代规则的关键是什么?为什么不使用列表呢?因为列表的杀伤力太大了。如果有一个函数,可以一个接一个地计算值,那么在使用时可能是计算一个值时获取一个值——而不是一次性获取所有值。如果有很多值,列表就会占用太多的内存。但还有其他的理由:使用迭代器更通用,更简单,更优雅。让我们看看一个不使用列表的例子,因为要用的话,列表长度必须无限。

  这里的“列表”是一个斐波那契数列。使用的迭代器如下:

class Fibs:
    def __init__(self):
        self.a = 0
        self.b = 1

    def __next__(self):
        self.a, self.b = self.b, self.a+self.b
        return self.a

    def __iter__(self):
        return self

fibs = Fibs()           # 创建一个斐波那契数列对象
for f in fibs:          # 对数列进行迭代
    if f > 100:
        print(f)
        break

使用迭代器

  注意:迭代器实现了__iter__方法,这个方法实际上返回迭代器本身。在很多情况下,__iter__会放到其他的会在for循环中使用的对象中。这样一来,程序就能返回所需要的迭代器。此外,推荐使用迭代器实现它自己的__iter__方法,然后就能直接在函数中使用迭代器本身了。

  **正式的说话是,一个实现了__iter__方法的对象是可迭代的,一个实现了next方法的对象则是迭代器。

  **内建函数iter可以从可迭代的对象中获得迭代器。此外,他也可以从函数或者其他可调用的对象中获取可迭代对象。

  从迭代器得到序列

  除了在迭代器和可迭代对象上进行迭代(这是经常做的)外,还能把它们转换为序列。在大部分能使用序列的情况下(除了在索引或者分片等操作中),都能使用迭代器(或者可迭代对象)替换。关于这个的的一个很有用的例子是使用list构造方法显示地将迭代器转化为列表。

class TestIterator:
    value = 0

    def next(self):
        self.value += 1
        if self.value > 10:
            raise StopIteration
        return self.value

    def __iter__(self):
        return self

ti = TestIterator()
list(ti)

  生成器

  生成器是一种普通的函数定义的迭代器。

 1 def flatten(nested):
 2     for sublist in nested:
 3         for element in sublist:
 4             yield element
 5
 6 nested = [[1, 2], [3, 4], [5]]
 7 for num in flatten(nested):
 8     print(num)
 9
10 -----结果
11 D:\Python27\python.exe D:/pythonwork/day04/iterator.py
12 1
13 2
14 3
15 4
16 5

  任何含有yield语句的函数都称为生成器。出名字不同以外,他的行为和普通的函数也是有很大的差别的。这就是它不是像return那样返回值,而是每次产生多个值。每次产生一个值(使用yield语句),函数就会被冻结:即函数停在那点等待被重新唤醒。函数唤醒后就从停止的那点开始执行。

  递归生成器

  要解决多层嵌套循环的问题,需要借助于递归(recursion)。如下:

 1 # 用递归解决多次嵌套循环问题
 2
 3
 4 def flatten(nested):
 5     # 处理异常
 6     try:
 7         for sublist in nested:
 8             for element in flatten(sublist):
 9                 yield element                  # 使用yield每次产生一个值,之后函数会被冻结,等待唤醒。
10     except TypeError:
11         yield nested

递归生成器Demo

  解析上述案例:

  当flatten被调用时,有两种可能性(处理递归时大部分都是有两种情况):基本情况和需要递归的情况。在基本情况下,函数被告知展开一个元素(比如一个数字)。这种情况下,for循环会引发一个TypeError异常(因为试图对一个数字进行迭代),生成器会产生一个元素。

  如果展开的是一个列表(或者其他的可迭代对象),那么就要进行特殊处理。程序必须遍历所有的子列表(一些可能不是列表),并对它们调用flatten函数。然后使用另外一个for循环来产生被展开的自列表的所有元素。

  *不应该flatten函数中对类似于字符串的对象进行迭代。处于两个原因。首先。需要实现的是将类似于字符串的对象当作原子值,而不是当成应被展开的序列。其次,对他们进行迭代,实际上会导致无穷递归,因为字符串的第一个元素是另外一个长度为1的字符串,而长度为1的字符串的第一个元素是其本身。

  为了处理这种情况,则必须在生成器开始处添加一个检查语句。试着将传入的对象和一个字符串拼接,看会不会出现TypeError,这是检查一个对象是不是类似于字符串的最简单,最快速的方法。如下代码(加入了检查语句):

 1 def flatten(nested):
 2     # 处理异常
 3     try:
 4         try: nested + ‘‘
 5         except TypeError: pass
 6         else: raise TypeError
 7         for sublist in nested:
 8             for element in flatten(sublist):
 9                 yield element                  # 使用yield每次产生一个值,之后函数会被冻结,等待唤醒。
10     except TypeError:
11         yield nested

Demo

  对代码进行解析:

  如果表达式nested+‘‘ 引发了一个TypeError,就会被忽略。然而如果没有引发TypeError,那么内层try语句中的else子句就会引发一个它自己的TypeError异常。这样就会按照原来的样子生成类似于字符串的对象(在except子句外面)。

  通用生成器

  生成器就是一种包含yield关键字的函数。当他被调用时,在函数体中的代码不会被执行,而会返回一个迭代器。每次请求一个值,就会执行生成器中的代码,知道遇到一个yield或者return语句。yield语句以为着应该生成一个值。return语句意味着生成器要停止执行(不再生成任何东西,return语句只有一个生成器中使用时才能进行无参数调用)。
  生成器是由两位部分组成:生成器的函数和生成器的迭代器。生成器的函数是用def语句定义的,包含yield的部分,生成器的迭代器是这个函数返回的部分。生成器的函数返回的迭代器可以像其他的迭代器那样使用。

  生成器方法

  send方法:

  “外部世界”作用域访问生成器的send方法,就像访问next方法一样,只不过前者使用一个参数(要发送的额“信息”——任意对象)。

  yield方法:

  在内部则挂起生成器,yield现在作为表达式而不是语句使用,换句话说,当生成器重新运行时,yield方法返回一个值,也就是外部通过send方法发送的值。

  注意:

  使用send方法(而不是next方法)只有在生成器挂起后才有意义(也就是说在yield函数第一次被执行后)。如果在此之前需要给生成器提供更多的信息,那么只需要使用生成器函数的参数。例如:

 1 def repeater(value):
 2     while True:
 3         new = (yield value)
 4         if new is not None:
 5             value = new
 6
 7
 8 r = repeater(43)
 9 print(r.__next__())
10 print(r.send("hello python!"))

  生成器还有两个其他的方法

  throw方法:使用异常类型调用,还有可选的值以及回溯对象,用于在生成器内引发一个异常(在yield表达式中)。

  close方法:用于停止生成器。

  模拟生成器

  例子如下:

 1 # 下面是flatten生成器用普通函数实现
 2 def flatten(nested):
 3     result = []
 4     try:
 5         # 不要迭代类似字符串的对象
 6         try:
 7             nested + ‘‘
 8         except TypeError: pass
 9         else: raise TypeError
10         for sublist in nested:
11             for element in flatten(sublist):
12                 result.append(element)
13     except TypeError:
14         result.append(nested)
15     return result

flatten生成器用普通函数实现

  装饰器

   见武sir博客:http://www.cnblogs.com/wupeiqi/articles/4943406.html

  

时间: 2024-10-08 10:13:32

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

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

本节大纲 迭代器&生成器 装饰器  基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式,运算后得出结果,结果必须与真实的计算器所得出的结果一致 迭代器&

python 迭代器 生成器 装饰器

迭代器 可以直接作用于for循环的对象统称为可迭代对象(Iterable). 可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator). 所有的Iterable均可以通过内置函数iter()来转变为Iterator. names = iter(['sun', 'ibm', 'sunny']) print(names) print(names.__next__()) print(names.__next__()) print(names.__next__()) print(

python -- 迭代器和装饰器

迭代器和装饰器在python中的使用十分常见,下面是个人对迭代器和装饰器的理解 迭代器 1.迭代器 iter 的特点: (1).访问者不需要关心迭代器的内部结构,仅需要通过__next__()方法不断去取下一个内容 (2).不能随机访问集合(不是set,只是一些元素的聚集体)中的某个值,只能从头到尾依次访问 (3).访问到一半时不能后退(过去的就过去了,不能回头) (4).便于循环比较大的数据集合,节省内存(每次需要了指定数据时,才把该读取到内存中,eg:迭代文件时,内存中每一时刻都只有文件的一

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

生成器 在Python中,一边循环一边计算的机制,称为生成器:generator. 如: 1 >>> g = (x * x for xin range(10)) 2 >>> g3 <generator object <genexpr> at 0x1022ef630> 此处g就是一个生成器. 迭代器 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是gene

Python 全栈开发五 迭代器 生成器 装饰器

一.迭代器 迭代器是一个可以记住遍历的位置的对象.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退. 迭代器有两个基本的方法:iter() 和 next(). 字符串,列表或元组对象都可用于创建迭代器,生成迭代器的方法是iter(): >>li = [1,2,3,4,5] >>it = iter(li) #生成一个迭代器 >>it.__next__() 1 >>next(it) #以上两种next都可以使用 2 >

迭代器/生成器/装饰器

迭代器 迭代器对象要求支持迭代器协议的对象,在Python中,支持迭代器协议就是实现对象的__iter__()和next()方法.其中__iter__()方法返回迭代器对象本身:next()方法返回容器的下一个元素,在结尾时引发StopIteration异常 可迭代对象 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration),默认的list.tuple.stri.dict对象都是可以迭代的. isinstance(obj

迭代器,生成器,装饰器,递归

迭代器 可迭代对象 1)定义:在python中,但凡内部含有--itter--方法的对象,都是可迭代对象 可以通过dir()去判断一个对象具有什么方法 dir()会返回一个列表,这个列表中含有该对象的以字符串形式的所有方法 从字面意思来说:可迭代对象就是一个可以重复取值的数据集. 从专业角度来说:但凡内部含有iter方法的对象,都是可迭代对象 . 可迭代对象可以通过判断该对象是否有’iter’方法来判断. 可迭代对象的优点: 可以直观的查看里面的数据.操作方法多,灵活 可迭代对象的缺点: 1.占

Day4 - Python基础4 迭代器、装饰器、软件开发规范

Python之路,Day4 - Python基础4 (new版) 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1,你怎么实现?你可能会想到2种方式 >>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>

Python_Day5_迭代器、装饰器、软件开发规范

本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 1.列表生成式,迭代器&生成器 列表生成 >>> a = [i+1 for i in range(10)] >>> a [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 生成器 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访

python学习笔记--装饰器

1.首先是一个很无聊的函数,实现了两个数的加法运算: def f(x,y): print x+y f(2,3) 输出结果也ok 5 2.可是这时候我们感觉输出结果太单一了点,想让代码的输出多一点看起来不这么单调: def showInfo(fun): def wrap(x,y): print "The function before" func(x,y) print "The function after" return wrap def f(x,y): print