4

抽象基底クラスを使用すると、Python は実際に試してみなくてもオブジェクトの動作を知る方法を提供します。標準ライブラリでは、 collections.abcにコンテナ用に定義されたいくつかの ABC があります。たとえば、引数が反復可能であることをテストできます。

from collections.abc import Iterable
def function(argument):
    if not isinstance(argument, Iterable):
        raise TypeError('argument must be iterable.')
    # do stuff with the argument

クラスのインスタンスを比較できるかどうかを判断するための ABC が 1 つあることを期待していましたが、見つけることができませんでした。メソッドの存在をテストする__lt__だけでは不十分です。たとえば、辞書は比較できませんが、__lt__まだ定義されています (object実際と同じ)。

>>> d1, d2 = {}, {}
>>> d1 < d2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: dict() < dict()
>>> hasattr(d1, '__lt__')
True

私の質問は次のとおりです。比較自体を行わずにキャッチする簡単な方法はありTypeErrorますか?

私の使用例は、並べ替えられたコンテナーに似ています。最初の要素を挿入するときに例外を発生させ、2 番目の要素を待たないようにしたいと考えています。要素をそれ自体と比較することを考えましたが、より良いアプローチはありますか:

def insert(self, element):
    try:
        element < element
    except TypeError as e:
        raise TypeError('element must be comparable.')
    # do stuff
4

1 に答える 1

5

いいえ、そのような ABC はありません。ABCは存在する属性のみを指示するためです。ABC は、実装の性質をテストすることはできません (または、それらの属性が実際にメソッドであっても)。

比較メソッド ( __lt____gt____le____ge__および__eq__) が存在するからといって、そのクラスが他のすべてのものと比較可能になるとは限りません通常、同じタイプまたはタイプのクラスのオブジェクトのみを比較できます。たとえば、数字と数字。

そのため、ほとんどの型は*比較メソッドを実装しますが、NotImplemented互換性のない他の型と比較するとセンチネル オブジェクトを返します。信号をPythonNotImplementedに戻して、右側の値にも問題について発言権を与えます。a.__lt__(b)返品されNotImplementedた場合b.__gt__(a)もテストされます。

ベースobjectはメソッドのデフォルトの実装を提供し、以下を返しNotImplementedます。

>>> class Foo:
...     pass
... 
>>> Foo() < Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: Foo() < Foo()
>>> Foo().__lt__
<method-wrapper '__lt__' of Foo object at 0x10f1cf860>
>>> Foo().__lt__(Foo())
NotImplemented

これはまさに次のことdict.__lt__です。

>>> {}.__lt__({})
NotImplemented

ただし、数値はNotImplemented、他の型が比較できない場合にのみ返されます。

>>> (1).__lt__(2)
True
>>> (1).__lt__('2')
NotImplemented
>>> 1 < 2
True
>>> 1 < '2'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < str()

そのため、値が比較できない場合は、スローされたものを単純にキャッチするのが最善の選択です。TypeError


*現時点で比較メソッドを実装していない Python 3 標準ライブラリの型は認識していません。

于 2015-04-05T12:15:23.900 に答える