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 相关文章推荐
Python脚本判断 Linux 是否运行在虚拟机上
Apr 25 Python
python基于右递归解决八皇后问题的方法
May 25 Python
python bottle框架支持jquery ajax的RESTful风格的PUT和DELETE方法
May 24 Python
利用Django内置的认证视图实现用户密码重置功能详解
Nov 24 Python
Python 16进制与中文相互转换的实现方法
Jul 09 Python
Python之两种模式的生产者消费者模型详解
Oct 26 Python
Python测试Kafka集群(pykafka)实例
Dec 23 Python
Python安装依赖(包)模块方法详解
Feb 14 Python
keras中的loss、optimizer、metrics用法
Jun 15 Python
Python自动发送和收取邮件的方法
Aug 12 Python
分享提高 Python 代码的可读性的技巧
Mar 03 Python
Pytorch中expand()的使用(扩展某个维度)
Jul 15 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
把从SQL中取出的数据转化成XMl格式
2006/10/09 PHP
PHPWind 发帖回帖Api PHP版打包下载
2010/02/08 PHP
codeigniter教程之上传视频并使用ffmpeg转flv示例
2014/02/13 PHP
PHP+redis实现的悲观锁机制示例
2018/06/12 PHP
解决AJAX中跨域访问出现'没有权限'的错误
2008/08/20 Javascript
用JavaScript玩转游戏物理(一)运动学模拟与粒子系统
2010/06/19 Javascript
基于Jquery制作的幻灯片图集效果打包下载
2011/02/12 Javascript
jquery五角星评分插件示例分享
2014/02/21 Javascript
js弹出确认是否删除对话框
2014/03/27 Javascript
js阻止事件追加的具体实现
2014/10/15 Javascript
JavaScript字符串对象fromCharCode方法入门实例(用于把Unicode值转换为字符串)
2014/10/17 Javascript
JS中完美兼容各大浏览器的scrolltop方法
2015/04/17 Javascript
js仿百度登录页实现拖动窗口效果
2016/03/11 Javascript
js的三种继承方式详解
2017/01/21 Javascript
最常用的jQuery表单验证(简单)
2017/05/23 jQuery
vue中使用cookies和crypto-js实现记住密码和加密的方法
2018/10/18 Javascript
大转盘抽奖小程序版 转盘抽奖网页版
2020/04/16 Javascript
vue cli 3.x 项目部署到 github pages的方法
2019/04/17 Javascript
通过实例解析JavaScript for in及for of区别
2020/06/15 Javascript
详解JavaScript中的数据类型,以及检测数据类型的方法
2020/09/17 Javascript
vue el-upload上传文件的示例代码
2020/12/21 Vue.js
[02:03]DOTA2亚洲邀请赛 HGT战队出场宣传片
2015/02/07 DOTA
[01:06:39]DOTA2上海特级锦标赛主赛事日 - 1 胜者组第一轮#1Liquid VS Alliance第三局
2016/03/02 DOTA
[01:32]完美世界DOTA2联赛10月29日精彩集锦
2020/10/30 DOTA
从零学python系列之教你如何根据图片生成字符画
2014/05/23 Python
Python3一行代码实现图片文字识别的示例
2018/01/15 Python
python画图把时间作为横坐标的方法
2019/07/07 Python
Python 字节流,字符串,十六进制相互转换实例(binascii,bytes)
2020/05/11 Python
html5构建触屏网站之网站尺寸探讨
2013/01/07 HTML / CSS
乌克兰在线商店的价格比较:Price.ua
2019/07/26 全球购物
升职演讲稿范文
2014/05/23 职场文书
初中家长评语和期望
2014/12/26 职场文书
见习期个人总结
2015/03/05 职场文书
三年级作文之小小梦想
2019/12/06 职场文书
windows安装python超详细图文教程
2021/05/21 Python
如何有效防止sql注入的方法
2021/05/25 SQL Server