Iterable object de-duplication (keep the order unchanged)
def filter_multi(items,key=None):"""
Iterable object de-duplication(Keep the order unchanged)[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 elsekey(x)if val not in its:yield val
its.append(val)
# Such as:
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'])))
Supplementary knowledge: Python feature learning-iterable objects, iterators (revised)
In the past, learning python was sloppy, leading to many features just knowing that they would not be used at all, now I will learn them again
Iterable
Simply put, all objects that can be put in a for loop are iterable objects, such as lists, tuples, strings, dictionaries...
How to determine whether an object is an iterable object?
In fact, as long as the object that implements the iter method is an iterable object, this method is used to return the iterator itself (particularly important).
eg:
s ="dasda"
s.__iter__()<str_iterator object at 0x7f23ebc44470
Python provides methods to determine whether it is an iterable object.
from collections import Iterable
isinstance(s,Iterable)
True
Iterator
It seems to be very similar to the above concept. In fact, all objects that implement the next() method are iterators. All objects that implement the next() and iter() methods are iterators, so all iterators can be put into a for loop.
There are not many native iterators in python, you can use iter() to generate iterators from iterable objects.
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__()1from collections import Iterator
isinstance(s,Iterator)
True
And the judgment method of iterator.
Make some distinctions
# coding=utf-8from collections import Iterable,Iterator
classA:#only__next__method. Not an iterator or an iterable object
def __init__(self,start,end):
self.start = start
self.end = end
def __next__(self):if self.start < self.end:
i = self.start
self.start +=1return i
else:
raise StopIteration()classB:#only__iter__method,__iter__Returned a no__next__Object. Is an iterable object, not an iterator
def __init__(self,start,end):
self.start = start
self.end = end
def __iter__(self):return self
classC:#only__iter__method,__iter__What is returned is a__next__Object. Is an iterable object, not an iterator
def __init__(self,start,end):
self.start = start
self.end = end
def __iter__(self):returnA(self.start,self.end)classD:#Existing__iter__Again__next__,__iter__What is returned is itself, there is__next__The objects are iterators and iterable objects
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 +=1return i
else:
raise StopIteration()classE:#Existing__iter__Again__next__,__iter__What is returned is not itself, there is__next__The objects are iterators and iterable objects
def __init__(self,start,end):
self.start = start
self.end = end
def __iter__(self):returnA(self.start,self.end)
def __next__(self):if self.start < self.end:
i = self.start
self.start +=1return i
else:
raise StopIteration()classF:#Existing__iter__Again__next__,__iter__Returned no__next__The objects are iterators and iterable objects
def __init__(self,start,end):
self.start = start
self.end = end
def __iter__(self):return1
def __next__(self):if self.start < self.end:
i = self.start
self.start +=1return 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))
operation result
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 loop
Obviously, list is an iterable object, which can be placed in a for loop. But list is not an iterator. After turning it into an iterator, it can also be placed in a for loop. So here comes the question:
**How does the for loop handle iterators and iterable objects? **
Let's try AF first, can you use 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
# Prompt is not an iterable object
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'
# prompt__iter__()Not an iterator
s =C(1,4)print('Iterable:',isinstance(s,Iterable))print('Iterator:',isinstance(s,Iterator))for i in s:print(i)-
Iterable: True
Iterator: False
123
# success
s =D(1,4)print('Iterable:',isinstance(s,Iterable))print('Iterator:',isinstance(s,Iterator))for i in s:print(i)-
Iterable: True
Iterator: True
123
# success
s =E(1,4)print('Iterable:',isinstance(s,Iterable))print('Iterator:',isinstance(s,Iterator))for i in s:print(i)-
Iterable: True
Iterator: True
123
# success
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'
# failure,__iter__Not an iterator
It can be seen that for can only work on iterable objects (note that Iterable and Iterator do not conflict, an object can be either Iterable or Iterator). Moreover, the iter of this iterable object only needs to return an object with next (even if it is not an iterator, such as C type, iter returns a type A that is not an iterator).
So the workflow of for:
Is there iter, if not, an error occurs
Call iter
The returned object keeps next() until StopIteration
to sum up
Iterable objects only need to have iter method, and it is not restricted to return objects with next
The iterator must have both iter and next, and the object returned by iter does not necessarily have a next method (type F).
The for loop can act on iterable objects. A successful for must be iter returns an object with next method.
doubt
Iterators must implement both next and iter, so does non-iterator mean non-iterator? But the object (A) returned by iter of class E is not an iterator but can also be for. How can this be explained?
Reply
There is a principle in Python, duck type, that is, as long as a creature looks like a duck, it is considered a duck.
The above python iterable object de-duplication example is all the content shared by the editor, I hope to give you a reference.
Recommended Posts