18

equals テストが必要な Python クラスがあります。Pythonはダックタイピングを使用する必要がありますが、(より良い/より正確に) isinstance テストをeq関数に含めるか除外しますか? 例えば:

class Trout(object):
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        return isinstance(other, Trout) and self.value == other.value
4

3 に答える 3

16

メソッドでisinstance を使用__eq__することは非常に一般的です。これは、メソッドが失敗した場合に、別のオブジェクト__eq__のメソッドにフォールバックできるためです。__eq__ほとんどの通常のメソッドは明示的に呼び出されますが、__eq__暗黙的に呼び出されるため、look-before-you-leap がより頻繁に必要になります。

編集(リマインダー、Sven Marnachに感謝):

フォールバックするには、次の例のように NotImplemented シングルトンを返すことができます。

class Trout(object):
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        if isinstance(other, Trout):
            return self.value == other.value
        else:
            return NotImplemented

a はRainbowTrout自分自身を aTroutまたは別のと比較する方法を知っているRainbowTroutが、 aTroutは自分自身を a と比較する方法しか知らないとしTroutます。この例で をテストするmytrout == myrainbowtroutと、Python は最初に を呼び出しmytrout.__eq__(myrainbowtrout)、失敗したことに気付き、次に を呼び出しmyrainbowtrout.__eq__(mytrout)て成功します。

于 2012-03-23T17:22:15.447 に答える
8

使用isintsance()は通常、__eq__()メソッドで問題ありません。Falseただし、チェックが失敗した場合にすぐに戻るべきではありません 。実行される機会を与えるためisinstance()に戻ったほうがよいでしょう。NotImplementedother.__eq__()

def __eq__(self, other):
    if isinstance(other, Trout):
        return self.x == other.x
    return NotImplemented

これは、複数のクラスが定義するクラス階層で特に重要になります__eq__()

class A(object):
    def __init__(self, x):
        self.x = x
    def __eq__(self, other):
        if isinstance(other, A):
            return self.x == other.x
        return NotImplemented
class B(A):
    def __init__(self, x, y):
        A.__init__(self, x)
        self.y = y
    def __eq__(self, other):
        if isinstance(other, B):
            return self.x, self.y == other.x, other.y
        return NotImplemented

元のコードのようにすぐに戻ると、とFalseの間の対称性が失われます。A(3) == B(3, 4)B(3, 4) == A(3)

于 2012-03-23T18:12:56.323 に答える
5

「ダックタイピング」の原則は、属性otherがある限り、何が何であるかは気にしないということです。valueしたがって、属性が競合するセマンティクスと名前を共有していない限り、次のようにすることをお勧めします。

def __eq__(self, other):
    try:
        return self.value == other.value
    except AttributeError:
        return False # or whatever

other(または、属性があるかどうかをテストすることもできますがvalue、「許可を得るよりも許しを求める方が簡単です」)

于 2012-03-23T17:28:49.857 に答える