python可迭代对象去重实例

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

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可迭代对象去重实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Python isinstance判断对象类型

    复制代码 代码如下: if (typeof(objA) == typeof(String)) { //TODO } 在Python中只需要使用内置的函数isinstance,使用起来非常简单,比如下面的例子: 复制代码 代码如下: class objA: pass A = objA() B = 'a','v' C = 'a string' print isinstance(A, objA) print isinstance(B, tuple) print isinstance(C, basest

  • Python判断变量是否已经定义的方法

    Python判断变量是否已经定义是一个非常重要的功能,本文就来简述这一功能的实现方法. 其实Python中有很多方法可以实现判断一个变量是否已经定义了.这里就举出最常用的两种作为示例,如下所示: 方法一:try except方法: def isset(v): try : type (eval(v)) except : return 0 else : return 1 用法: if isset('user_name'): print 'user_name is defined' else prin

  • 详解Python迭代和迭代器

    我们将要来学习python的重要概念迭代和迭代器,通过简单实用的例子如列表迭代器和xrange. 可迭代 一个对象,物理或者虚拟存储的序列.list,tuple,strins,dicttionary,set以及生成器对象都是可迭代的,整型数是不可迭代的.如果你不确定哪个可迭代哪个不可以,你需要用python内建的iter()来帮忙. >>> iter([1,2,3]) <listiterator object at 0x026C8970> >>> iter(

  • Python迭代用法实例教程

    本文实例讲述了Python中迭代的用法,是一个非常实用的技巧.分享给大家供大家参考借鉴之用.具体分析如下: 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们成为迭代(Iteration). 在Python中,迭代是通过for ... in来完成的,而很多语言比如C或者Java,迭代list是通过下标完成的,比如Java代码: for (i=0; i<list.length; i++) { n = list[i]; } 可以看出,Python的f

  • python可迭代对象去重实例

    可迭代对象去重(保持顺序不变) 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) #如:

  • Python可迭代对象操作示例

    本文实例讲述了Python可迭代对象.分享给大家供大家参考,具体如下: 1.列表生成式 list = [result for x in range(m, n)] g1 = (i for i in range(101)) print(type(g1)) print(g1) print(g1.__next__()) 输出: <class 'generator'> <generator object <genexpr> at 0x0000024E6AC08F10> 0 g1

  • 一文带你解密Python可迭代对象的排序问题

    假设有一个可迭代对象,现在想要对它内部的元素进行排序,我们一般会使用内置函数 sorted,举个例子: data = (3, 4, 1, 2, 5) print(     sorted(data) )  # [1, 2, 3, 4, 5] data = (3.14, 2, 1.75) print(     sorted(data) )  # [1.75, 2, 3.14] data = ["satori", "koishi", "marisa"]

  • Python 可迭代对象 iterable的具体使用

    目录 前置知识 可迭代对象 如何判断一个对象是否是可迭代对象? enumerate 函数 多嵌套列表 总结 前置知识 如果给定一个 list 或 tuple,我们可以通过 for 循环来遍历这个 list 或 tuple,这种遍历我们称为迭代(Iteration) 在 Python 中,迭代是通过 for ... in 来完成的 lists = [1, 2, 3, 4, 5] for i in lists: print(i) 可迭代对象 for 循环不仅可以用在 list 或 tuple 上,还

  • 一文搞懂​​​​​​​python可迭代对象,迭代器,生成器,协程

    目录 设计模式:迭代 python:可迭代对象和迭代器 为什么要有生成器? python的生成器实现 协程 设计模式:迭代 迭代是一种设计模式,解决有序便利序列的问题.通用的可迭代对象需要支持done和next方法. 伪代码如下: while not iterator.done(): item = iterator.next() ..... python:可迭代对象和迭代器 python的可迭代对象需要实现__iter__()方法,返回一个迭代器.for循环和顶级函数iter(obj)调用obj

  • python学习之可迭代对象、迭代器、生成器

    Iterable – 可迭代对象 能够逐一返回其成员项的对象. 可迭代对象的例子包括所有序列类型 (例如 list, str 和 tuple) 以及某些非序列类型例如 dict, 文件对象以及定义了__iter__()方法或是实现了序列语义的__getitem__() 方法的任意自定义类对象. 可迭代对象可用于 for 循环以及许多其他需要一个序列的地方(zip().map() -).当一个可迭代对象作为参数传给内置函数 iter() 时,它会返回该对象的迭代器.这种迭代器适用于对值集合的一次性

  • Python cookbook(数据结构与算法)从任意长度的可迭代对象中分解元素操作示例

    本文实例讲述了python从任意长度的可迭代对象中分解元素操作.分享给大家供大家参考,具体如下: 从某个可迭代对象中分解出N个元素,但是可迭代对象的长度可能超过N,会出现"分解值过多"的异常: 使用"*表达式"来解决该问题: Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit (Intel)] on win32 Type "copyright",

  • python使用生成器实现可迭代对象

    本文实例为大家分享了python使用生成器实现可迭代对象的具体代码,供大家参考,具体内容如下 案例分析: 实一个可迭代对象的类,它能迭代出给定范围内所有的素数: pn = Number(1, 30) for k in pn: print(k) 结果为:2,3,5,7,11,13,17,19,23,29 如何解决这个问题? 将该类的__iter__方法实现成生成器函数,每次yield返回一个素数 #!/usr/bin/python3 class Number(object): def __init

  • Python List列表对象内置方法实例详解

    本文实例讲述了Python List列表对象内置方法.分享给大家供大家参考,具体如下: 前言 在上一篇中介绍了Python的序列和String类型的内置方法,本篇继续学习作为序列类型成员之一的List类型的内置方法. 软件环境 系统 UbuntuKylin 14.04 软件 Python 2.7.3 IPython 4.0.0 列表List 列表是一种容器,存放内存对象的引用.即是任意内存对象的有序集合,不同的类型对象可以存放在同一个列表中.通过索引来访问其中的元素.可以任意的嵌套.伸长.异构.

  • Python中for循环可迭代对象迭代器及生成器源码学习

    目录 问题: 1. 迭代 1.1 可迭代对象Iterable 1.2 迭代器Iterator 1.3 for循环 1.3.1 iter()方法和next()方法 1.3.2 iter()和__iter__() 1.3.3 next()和__next__() 1.3.4 自定义类实现__iter__()和__next__() 1.3.5 探究for循环 2 生成器 2.1 获取生成器 2.2 next(生成器) 2.3 生成器和迭代器 2.4 生成器解析式 问题: 之前在学习list和dict相关

随机推荐