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清理子进程机制剖析
Nov 23 Python
Python3多线程操作简单示例
May 22 Python
Tensorflow中使用tfrecord方式读取数据的方法
Jun 19 Python
matplotlib给子图添加图例的方法
Aug 03 Python
在Qt5和PyQt5中设置支持高分辨率屏幕自适应的方法
Jun 18 Python
Django 迁移、操作数据库的方法
Aug 02 Python
python实现复制大量文件功能
Aug 31 Python
Python AutoCAD 系统设置的实现方法
Apr 01 Python
pandas中read_csv、rolling、expanding用法详解
Apr 21 Python
Python操控mysql批量插入数据的实现方法
Oct 27 Python
Python 如何解决稀疏矩阵运算
May 26 Python
python编程实现清理微信重复缓存文件
Nov 01 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
玛琪朵 Macchiato
2021/03/03 咖啡文化
php数字游戏 计算24算法
2012/06/10 PHP
完美解决thinkphp验证码出错无法显示的方法
2014/12/09 PHP
PHP连接数据库实现注册页面的增删改查操作
2016/03/27 PHP
PHP实现支持加盐的图片加密解密
2016/09/09 PHP
Laravel实现autoload方法详解
2017/05/07 PHP
php xhprof使用实例详解
2019/04/15 PHP
推荐17个优美新鲜的jQuery的工具提示插件
2012/09/14 Javascript
jquery重新播放css动画所遇问题解决
2013/08/21 Javascript
将查询条件的input、select清空
2014/01/14 Javascript
jQuery动态修改超链接地址的方法
2015/02/13 Javascript
jQuery实现底部浮动窗口效果
2016/09/07 Javascript
JS实现的简单图片切换功能示例【测试可用】
2017/02/14 Javascript
原生js仿淘宝网商品放大镜效果
2017/02/28 Javascript
利用ES6的Promise.all实现至少请求多长时间的实例
2017/08/28 Javascript
从源码看angular/material2 中 dialog模块的实现方法
2017/10/18 Javascript
JavaScript实现图片轮播特效
2019/10/23 Javascript
Vue中keep-alive的两种应用方式
2020/07/15 Javascript
vue或react项目生产环境去掉console.log的操作
2020/09/02 Javascript
JS画布动态实现黑客帝国背景效果
2020/11/08 Javascript
[01:00:59]VP VS VG Supermajor小组赛胜者组第二轮 BO3第二场 6.2
2018/06/03 DOTA
Python中的zipfile模块使用详解
2015/06/25 Python
Python的mysql数据库的更新如何实现
2017/07/31 Python
python3.6.3+opencv3.3.0实现动态人脸捕获
2018/05/25 Python
pandas数据筛选和csv操作的实现方法
2019/07/02 Python
如何在django中添加日志功能
2020/02/06 Python
python实现简单坦克大战
2020/03/27 Python
在keras中对单一输入图像进行预测并返回预测结果操作
2020/07/09 Python
超酷炫 CSS3垂直手风琴菜单
2016/06/28 HTML / CSS
EQVVS官网:设计师男装和女装
2018/10/24 全球购物
美国相机和电子产品零售商:Beach Camera
2020/11/26 全球购物
关键字final的用法
2013/10/02 面试题
承诺函格式模板
2015/01/21 职场文书
上课迟到检讨书
2015/05/06 职场文书
小学生手册家长意见
2015/06/03 职场文书
详解Spring Security中的HttpBasic登录验证模式
2022/03/17 Java/Android