python 迭代器 一个奇怪的解决方法

  一般我们在类里面写迭代器都是如下写法:

  

1 class IterableSomthing:
2     def __iter__(self):
3         return self
4
5     def __next__(self):
6         return 1

  但是,《流畅的python》给出了不同的见解。该书指出,在数据结构内实现迭代器是个很蠢的想法,因为需要引入游标指针记录位置的缘故,这么实现迭代器会造成数据结构空间性能下降,同时,因为游标指针的独立性使得改数据结构无法并发遍历,所以又造成了时间性能的下降。代码如下

  1 class Node:
  2     def __init__(self, item):
  3         self.item = item
  4         self.pre = None
  5         self.next = None
  6
  7
  8 class Deque:
  9     def __init__(self):
 10         """创建一个空的双端队列"""
 11         self.head = None
 12         self.tail = None
 13         self.point = self.head  #游标指针
 14
 15     def add_front(self, item):
 16         """从队头加入一个item元素"""
 17         n0 = Node(item)
 18         if self.head:
 19             n0.next = self.head
 20             self.head.pre = n0
 21             self.head = n0
 22         else:
 23             self.head = n0
 24             self.tail = n0
 25         self.zero()
 26
 27     def add_rear(self, item):
 28         """从队尾加入一个item元素"""
 29         n0 = Node(item)
 30         if self.tail:
 31             n0.pre = self.tail
 32             self.tail.next = n0
 33             self.tail = n0
 34         else:
 35             self.head = n0
 36             self.tail = n0
 37         self.zero()
 38
 39     def remove_front(self):
 40         """从队头删除一个item元素"""
 41         if self.head:
 42             if self.head == self.tail:
 43                 self.head = None
 44                 self.tail = None
 45             else:
 46                 self.head.next.pre = None
 47                 self.head = self.head.next
 48         self.zero()
 49
 50     def remove_rear(self):
 51         """从队尾删除一个item元素"""
 52         if self.tail:
 53             if self.head == self.tail:
 54                 self.head = None
 55                 self.tail = None
 56             else:
 57                 self.tail.pre.next = None
 58                 self.tail = self.tail.pre
 59         self.zero()
 60
 61     def is_empty(self):
 62         """判断双端队列是否为空"""
 63         return self.head is None
 64
 65     def size(self):
 66         """返回队列的大小"""
 67         i = 0
 68         n0 = self.head
 69         while n0:
 70             i += 1
 71             n0 = n0.next
 72         return i
 73
 74     def tolist(self):
 75         li = []
 76         n0 = self.head
 77         while n0:
 78             li.append(n0.item)
 79             n0 = n0.next
 80         return li
 81
 82     def gen(self):
 83         n0 = self.head
 84         while n0:
 85             # print(id(self))
 86             yield n0.item
 87             n0 = n0.next
 88         raise StopIteration
 89
 90     def __iter__(self):
 91         # n0 = self.head
 92         # while n0:
 93         #     # print(id(self))
 94         #     yield n0.item
 95         #     n0 = n0.next
 96         # raise StopIteration
 97         return self
 98
 99     def __next__(self):
100         if self.point:
101             n0 = self.point
102             self.point = self.point.next
103             return n0.item
104         else:
105             self.zero()
106             raise StopIteration
107
108     def zero(self):  #游标指针归零函数
109         self.point = self.head

这是个双端队列的python实现,如果实现了迭代器,就必须实现游标指针类属性,游标指针归零类方法,着实降低了开发效率

有没有别的解决方法呢?

只要改一处:

1     def __iter__(self):
2         __index_temp = self.__head
3         while __index_temp:
4             n0 = __index_temp
5             __index_temp = __index_temp.next
6             yield n0
7         else:
8             raise StopIteration

对你没看错,没有__next__函数!没有游标指针!没有归零函数!

这个__iter__函数需要返回一个迭代器,我们就给他一个,因为生成器也是迭代器!

此时,这个双端队列的python实现就不是一个迭代器了,而是一个可迭代对象,就可以用for循环迭代了

def test2():
    s1 = DoubleLinkList()
    for i in range(1000):
        s1.append(i)
    for ii in s1:
        print(ii.item)
        if ii.item == 500:
            print(‘------------------------------------------------------------------------------‘)
            break
    for ii in s1:
        print(ii.item)

而且每一个for循环都是独立的,因为每个for循环块获得的对象都是一个独立的生成器,相互之间不会干扰,虽然看起来都是调用同一个对象,但实际上完全不是这么一回事,这就和list的实现是一样一样的,这样的话做并发循环就容易多了。

思考:python里的魔术方法都很有用,但是我们是要为了实现某个功能专门实现对应的魔术方法呢,还是直接实现对应的功能函数呢?

      魔术方法是为了其他方法服务的基本方法,还是锦上添花的增补手段呢?

时间: 2024-10-01 02:42:22

python 迭代器 一个奇怪的解决方法的相关文章

python 进程内存增长问题, 解决方法和工具

python 进程内存增长问题, 解决方法和工具 表现 解决方法 定位问题过程 gdb-python: 搞清楚python程序在做什么 准备gdb 接入gdb 查看线程 查看调用栈 coredump 其他命令 pyrasite: 连接进入python程序 psutil 查看python进程状态 guppy 取得内存使用的各种对象占用情况 无法回收的对象 不可回收对象的例子 ?? objgraph 查找循环引用 表现 运行环境: # uname -a Linux ** 3.10.0-327.el7

Emgu CV的一个异常的解决方法

今年组里有大项目落我头上了,并不能像去年一样回家还能搞搞Cocos2dX,一把老泪流了下来... 回到正题,由于组里需要做一个显示板的自动测试项目,涉及到Computer Vision.不得不说,这才是项目里的大坑.之前一直在做其他基础库的研发,最近开始了视觉识别的研发进度.由于市面上没有很合适的开源工业摄影机,只能硬着头皮先试试一些已经有先例的视觉库来尝试.前期项目架构在C#上,自然而然就想到了OpenCV在包装C#的库Emgu CV,而且这个库跨平台,很适合后期移植到其他平台上去,我就选择了

python socket.error: [Errno 10054] 解决方法

我用的是python2.7   我搜网上10054错误解决方法的时候发现,大部分文章都是以python3为基础的,对于python2不适用. python socket.error: [Errno 10054]  远程主机强迫关闭了一个现有的连接. 原因:服务器发现你的爬虫行为了,所有强制断开链接了 解决办法:  服务器知道你是爬虫,加headers, 模拟浏览器agent:head中有一个user-agent每次都换不同的模拟代理 #coding:utf-8 import urllib2 ur

在spark中遇到了奇怪的错误,找到了奇怪的解决方法

这两天一直在写spark程序,遇到了一个奇怪的问题. 问题简单描述如下,有两个RDD,设为rdd_a,rdd_b,当将这两个rdd合并的时候,spark会在运行中卡死. 解决方式也是奇葩. 只要在合并这两个rdd之前,分别执行rdd_a.count(),rdd_b.count(),程序就又能够愉快的走下去了. 参考: stackOverFlow

C# 该行已经属于另一个表 的解决方法[转]

该文转自:http://blog.sina.com.cn/s/blog_48e4c3fe0100nzs6.html DataTable dt = new DataTable(); dt = ds.Tables["All"].Clone();//把All的结构传递给dt DataRow[] dr=this.dataSet31.Tables["Product"].Select("bc=1");for(int i=0;i<dr.Length;i+

windows下Python开发错误记录以及解决方法

windows下使用pip提示ImportError: cannot import name 'main' 原因:将pip更新为10.0.0后库里面的函数有所变动造成这个问题 解决方法:先卸载现在的pip: python -m pip uninstall pip 然后重装:python -m pip install pip==19.0.3 原文地址:https://www.cnblogs.com/mm1994/p/11763860.html

Python pip下载慢的解决方法

国外的源下载速度实在是太慢了 可以使用国内的一些镜像网站安装 使用cmd命令 格式:pip install -i 网站 库 例如: 国内的一些镜像网站 清华大学:https://pypi.tuna.tsinghua.edu.cn/simple 阿里云:http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/ 华中科技大学:http://pypi.hustunique.com/ 山东

Python 中文注释报错解决方法

代码中一旦有了中文注释便会报错. 原因 如果文件里有非ASCII字符,需要在第一行或第二行指定编码声明. 解决方法 在第一行或是第二行加入这么一句# -- coding: utf-8 -- 完美解决

Python学习之异常重试解决方法详解

本文和大家分享的是在使用python 进行数据抓取中,异常重试相关解决办法,一起来看看吧,希望对大家学习python有所帮助. 在做数据抓取的时候,经常遇到由于网络问题导致的程序保存,先前只是记录了错误内容,并对错误内容进行后期处理. 原先的流程: defcrawl_page(url): pass deflog_error(url): pass url = "" try: crawl_page(url) except: log_error(url) 改进后的流程: attempts =