python可迭代对象去重实例


Posted in Python onMay 15, 2020

可迭代对象去重(保持顺序不变)

def filter_multi(items,key=None):
 """
 可迭代对象去重(保持顺序不变)
 [1,4,7,2,4,7,3,5] ==> [1,4,7,2,3,5]
 """
 its = list()
 for x in items:
 val = x if key is None else key(x)
 if val not in its:
 yield val
 its.append(val)
#如:
print list(filter_multi([1,3,5,3,7,2,4,2]))
 
items = [{'a':1,'b':2},{'a':3,'b':4},{'a':1,'b':2},{'a':5,'b':6}]
print list(filter_multi(items,key=lambda k:(k['a'],k['b'])))

补充知识:Python特性学习——可迭代对象,迭代器(重新修正)

以前学习python都是马马虎虎,导致很多特性只是知道完全不会用,现在将他们重新学习

可迭代对象(Iterable)

简单来说,所有可以放入for循环中的对象都是可迭代对象,如列表,元组,字符串,字典…

如何判断对象是否是可迭代对象?

实际上,只要实现了__iter__方法的对象就是可迭代对象,这个方法用来返回迭代器本身(特别重要)。

eg:

>>> s = "dasda"
>>> s.__iter__()
<str_iterator object at 0x7f23ebc44470>

python提供了方法判断是否是可迭代对象。

>>> from collections import Iterable
>>> isinstance(s,Iterable)
True

迭代器(Iterator)

似乎和上面的概念很相似。实际上,所有实现了__next__()方法的对象都是迭代器。所有实现了__next__()和__iter__()方法的对象都是迭代器,所以,所有的迭代器都能放入for循环。

python中原生的迭代器不多,可以使用iter()将可迭代对象生成迭代器。

eg:

>>> s = [1,2,3,4,5]
>>> s.__next__()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute '__next__'
>>> s = iter(s)
>>> type(s)
<class 'list_iterator'>
>>> s.__next__()
1
>>> from collections import Iterator
>>> isinstance(s,Iterator)
True

以及迭代器的判断方法。

做一些区分

#coding=utf-8
from collections import Iterable,Iterator

class A:#只有__next__方法。不是迭代器也不是可迭代对象
 def __init__(self,start,end):
  self.start = start
  self.end = end

 def __next__(self):
  if self.start < self.end:
   i = self.start
   self.start += 1
   return i
  else:
   raise StopIteration()

class B:#只有__iter__方法,__iter__返回的是一个没有__next__的对象。是可迭代对象,不是迭代器
 def __init__(self,start,end):
  self.start = start
  self.end = end

 def __iter__(self):
  return self

class C:#只有__iter__方法,__iter__返回的是一个有__next__的对象。是可迭代对象,不是迭代器
 def __init__(self,start,end):
  self.start = start
  self.end = end

 def __iter__(self):
  return A(self.start,self.end)

class D:#既有__iter__又有__next__,__iter__返回的是自身,有__next__的对象,是迭代器和可迭代对象
 def __init__(self,start,end):
  self.start = start
  self.end = end

 def __iter__(self):
  return self

 def __next__(self):
  if self.start < self.end:
   i = self.start
   self.start += 1
   return i
  else:
   raise StopIteration()

class E:#既有__iter__又有__next__,__iter__返回的不是自身,有__next__的对象,是迭代器和可迭代对象
 def __init__(self,start,end):
  self.start = start
  self.end = end

 def __iter__(self):
  return A(self.start,self.end)

 def __next__(self):
  if self.start < self.end:
   i = self.start
   self.start += 1
   return i
  else:
   raise StopIteration()

class F:#既有__iter__又有__next__,__iter__返回的是没有__next__的对象,是迭代器和可迭代对象
 def __init__(self,start,end):
  self.start = start
  self.end = end

 def __iter__(self):
  return 1

 def __next__(self):
  if self.start < self.end:
   i = self.start
   self.start += 1
   return i
  else:
   raise StopIteration()

s = A(5,10)
print('Iterable:',isinstance(s,Iterable))
print('Iterator:',isinstance(s,Iterator))

s = B(5,10)
print('Iterable:',isinstance(s,Iterable))
print('Iterator:',isinstance(s,Iterator))

s = C(5,10)
print('Iterable:',isinstance(s,Iterable))
print('Iterator:',isinstance(s,Iterator))

s = D(5,10)
print('Iterable:',isinstance(s,Iterable))
print('Iterator:',isinstance(s,Iterator))


s = E(5,10)
print('Iterable:',isinstance(s,Iterable))
print('Iterator:',isinstance(s,Iterator))

s = F(5,10)
print('Iterable:',isinstance(s,Iterable))
print('Iterator:',isinstance(s,Iterator))

运行结果

Iterable: False
Iterator: False

Iterable: True
Iterator: False

Iterable: True
Iterator: False

Iterable: True
Iterator: True

Iterable: True
Iterator: True

Iterable: True
Iterator: True

for循环

很明显看出,list是一个可迭代对象,它能放到for循环里。但list不是迭代器,把它变成迭代器后,也能放入for循环中。那么问题来了:

for循环如何处理迭代器和可迭代对象的呢?

先来试试A-F都能不能用for

s = A(1,4)
for i in s:
 print(i)

->

Traceback (most recent call last):
 File "IteratorZZ.py", line 68, in <module>
 for i in s:
TypeError: 'A' object is not iterable
#提示并非一个可迭代对象
s = B(1,4)
print('Iterable:',isinstance(s,Iterable))
print('Iterator:',isinstance(s,Iterator))
for i in s:
 print(i)

->

Iterable: True
Iterator: False
Traceback (most recent call last):
 File "IteratorZZ.py", line 75, in <module>
 for i in s:
TypeError: iter() returned non-iterator of type 'B'
#提示__iter__()返回的不是一个迭代器
s = C(1,4)
print('Iterable:',isinstance(s,Iterable))
print('Iterator:',isinstance(s,Iterator))
for i in s:
 print(i)

->

Iterable: True
Iterator: False
1
2
3
#成功
s = D(1,4)
print('Iterable:',isinstance(s,Iterable))
print('Iterator:',isinstance(s,Iterator))
for i in s:
 print(i)

->

Iterable: True
Iterator: True
1
2
3
#成功
s = E(1,4)
print('Iterable:',isinstance(s,Iterable))
print('Iterator:',isinstance(s,Iterator))
for i in s:
 print(i)

->

Iterable: True
Iterator: True
1
2
3
#成功
s = F(1,4)
print('Iterable:',isinstance(s,Iterable))
print('Iterator:',isinstance(s,Iterator))
for i in s:
 print(i)

->
Iterable: True
Iterator: True
Traceback (most recent call last):
 File "IteratorZZ.py", line 115, in <module>
 for i in s:
TypeError: iter() returned non-iterator of type 'int'
#失败,__iter__返回的不是迭代器

由此可见,for只能作用在可迭代对象上(注意,Iterable和Iterator不冲突,一个对象即可以是Iterable也可以是Iterator)。并且,这个可迭代对象的__iter__返回的只需要是一个有__next__的对象(即便它不是迭代器,如C类,__iter__返回的是并非迭代器的A类)。

所以for的工作流程:

1. 是否有__iter__,没有则出错

2. 调用__iter__

3. 返回的对象不断next()直到StopIteration

总结

可迭代对象只需有__iter__方法,并且不限制它非得返回有__next__的对象

迭代器必须同时拥有__iter__和__next__,并且__iter__返回的对象不一定有__next__方法(F类)。

for循环可以作用在可迭代对象上。成功的for必须是__iter__返回有__next__方法的对象。

疑问

迭代器必须同时实现__next__和__iter__,那non-iterator是不是说的是非迭代器呢?但是E类的__iter__返回的对象(A)不是迭代器但也能for,这该怎么解释呢?

回答

Python里有一个原则,鸭子类型,即只要一个生物长得像鸭子,就认为它是鸭子。

以上这篇python可迭代对象去重实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
在Windows服务器下用Apache和mod_wsgi配置Python应用的教程
May 06 Python
Python统计日志中每个IP出现次数的方法
Jul 06 Python
以视频爬取实例讲解Python爬虫神器Beautiful Soup用法
Jan 20 Python
Python备份目录及目录下的全部内容的实现方法
Jun 12 Python
python 与GO中操作slice,list的方式实例代码
Mar 20 Python
通过源码分析Python中的切片赋值
May 08 Python
Python3.5字符串常用操作实例详解
May 01 Python
Python类和实例的属性机制原理详解
Mar 21 Python
python调用win32接口进行截图的示例
Nov 11 Python
opencv+pyQt5实现图片阈值编辑器/寻色块阈值利器
Nov 13 Python
基于Python实现天天酷跑功能
Jan 06 Python
python 统计list中各个元素出现的次数的几种方法
Feb 20 Python
python 操作mysql数据中fetchone()和fetchall()方式
May 15 #Python
Python实现UDP程序通信过程图解
May 15 #Python
解决pymysql cursor.fetchall() 获取不到数据的问题
May 15 #Python
python如何解析复杂sql,实现数据库和表的提取的实例剖析
May 15 #Python
pymysql之cur.fetchall() 和cur.fetchone()用法详解
May 15 #Python
django 利用Q对象与F对象进行查询的实现
May 15 #Python
Python实现电视里的5毛特效实例代码详解
May 15 #Python
You might like
phpMyAdmin出现无法载入 mcrypt 扩展,请检查PHP配置的解决方法
2012/03/26 PHP
PHP使用CURL_MULTI实现多线程采集的例子
2014/07/29 PHP
laravel 4安装及入门图文教程
2014/10/29 PHP
PHP二维数组排序简单实现方法
2016/02/14 PHP
PHP实现的折半查询算法示例
2017/10/09 PHP
PHP读取并输出XML文件数据的简单实现方法
2017/12/22 PHP
PHP创建对象的六种方式实例总结
2019/06/27 PHP
jQuery 加上最后自己的验证
2009/11/04 Javascript
jQuery源码分析-03构造jQuery对象-工具函数
2011/11/14 Javascript
Jquery获得控件值的三种方法总结
2014/02/13 Javascript
使用Nodejs开发微信公众号后台服务实例
2014/09/03 NodeJs
使用微信内置浏览器点击下拉框出现页面乱跳转现象(iphone),该怎么办
2016/01/04 Javascript
jQuery设置单选按钮radio选中/不可用的实例代码
2016/06/24 Javascript
AngularJS表达式讲解及示例代码
2016/08/16 Javascript
详解Angular的数据显示优化处理
2016/12/26 Javascript
node.js中cluster的使用教程
2017/06/09 Javascript
一个基于react的图片裁剪组件示例
2018/04/18 Javascript
使用json-server简单完成CRUD模拟后台数据的方法
2018/07/12 Javascript
原生JS forEach()和map()遍历的区别、兼容写法及jQuery $.each、$.map遍历操作
2019/02/27 jQuery
微信自定义分享链接信息(标题,图片和内容)实现过程详解
2019/09/04 Javascript
[07:54]DOTA2-DPC中国联赛 正赛 iG vs VG 选手采访
2021/03/11 DOTA
python处理json数据中的中文
2014/03/06 Python
Python备份目录及目录下的全部内容的实现方法
2016/06/12 Python
Python脚本获取操作系统版本信息
2016/12/17 Python
python3 cvs将数据读取为字典的方法
2018/12/22 Python
Python类及获取对象属性方法解析
2020/06/15 Python
浅谈CSS3 box-sizing 属性 有趣的盒模型
2019/04/02 HTML / CSS
Carter’s官方旗舰店:美国受欢迎的婴童服装品牌
2018/01/21 全球购物
生产部主管岗位职责
2014/01/06 职场文书
2014优秀党员事迹材料
2014/08/14 职场文书
党员批评与自我批评材料
2014/10/14 职场文书
交心谈心活动总结
2015/05/11 职场文书
沂蒙六姐妹观后感
2015/06/08 职场文书
证婚人婚礼致辞
2015/07/28 职场文书
幼儿园老师新年寄语
2015/08/17 职场文书
财产分割协议书
2016/03/22 职场文书