反復可能なオブジェクトの重複排除(順序は変更されません)
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 elsekey(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の学習はお粗末で、まったく使用されないことを知っているだけで多くの機能につながりましたが、今度はそれらをもう一度学習します
反復可能(反復可能)
簡単に言えば、forループに入れることができるすべてのオブジェクトは、リスト、タプル、文字列、辞書などの反復可能なオブジェクトです。
オブジェクトが反復可能なオブジェクトであるかどうかを判断するにはどうすればよいですか?
実際、__ iter__メソッドを実装するオブジェクトが反復可能オブジェクトである限り、このメソッドは反復子自体を返すために使用されます(特に重要です)。
eg:
s ="dasda"
s.__iter__()<str_iterator object at 0x7f23ebc44470
Pythonは、それが反復可能なオブジェクトであるかどうかを判別するためのメソッドを提供します。
from collections import Iterable
isinstance(s,Iterable)
True
イテレーター
上記の考え方とよく似ているようです。実際、__ 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__()1from collections import Iterator
isinstance(s,Iterator)
True
そして、イテレーターの判断方法。
いくつかの区別をする
# coding=utf-8from collections import Iterable,Iterator
classA:#のみ__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 +=1return i
else:
raise StopIteration()classB:#のみ__iter__方法、__iter__いいえを返しました__next__オブジェクト。反復可能オブジェクトであり、反復子ではありません
def __init__(self,start,end):
self.start = start
self.end = end
def __iter__(self):return self
classC:#のみ__iter__方法、__iter__返されるのは__next__オブジェクト。反復可能オブジェクトであり、反復子ではありません
def __init__(self,start,end):
self.start = start
self.end = end
def __iter__(self):returnA(self.start,self.end)classD:#既存__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 +=1return i
else:
raise StopIteration()classE:#既存__iter__再び__next__,__iter__返されるのはそれ自体ではなく、__next__オブジェクトはイテレーターとイテラブルオブジェクトです
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:#既存__iter__再び__next__,__iter__返されません__next__オブジェクトはイテレーターとイテラブルオブジェクトです
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))
運用結果
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ループに配置できます。ただし、リストはイテレーターではありません。イテレーターに変換した後、forループに配置することもできます。だからここに質問が来ます:
**forループはイテレーターとイテラブルオブジェクトをどのように処理しますか? ****
まずAFを試してみましょう。
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
123
# 成功
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
# 成功
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
# 成功
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:**のワークフロー
__iter__はありますか、ない場合はエラーが発生します
__iter__に電話する
返されたオブジェクトは、StopIterationまでnext()を保持します
総括する
反復可能なオブジェクトには__iter__メソッドのみが必要であり、__ next__でオブジェクトを返すように制限されていません。
イテレーターには__iter__と__next__の両方が必要であり、__ iter__によって返されるオブジェクトには必ずしも__next__メソッド(タイプF)が含まれているとは限りません。
forループは、反復可能なオブジェクトに作用できます。成功する必要があります__iter__は__next__メソッドでオブジェクトを返します。
疑問に思う
イテレーターは__next__と__iter__の両方を実装する必要があるので、非イテレーターは非イテレーターを意味しますか?しかし、クラスEの__iter__によって返されるオブジェクト(A)は、反復子ではありませんが、反復子にすることもできます。これはどのように説明できますか?
応答
Pythonにはアヒルの種類という原則があります。つまり、クリーチャーがアヒルのように見える限り、アヒルと見なされます。
上記のpythoniterableオブジェクトの重複排除の例は、エディターによって共有されるすべてのコンテンツです。参照を提供したいと思います。
Recommended Posts