3

を使用して 2 つの変数を==比較すると、Python は ID を比較し、それらが同じでない場合は値を比較しますか?

たとえば、同じ文字列オブジェクトを指す 2 つの文字列があります。

>>> a = 'a sequence of chars'
>>> b = a

これは値を比較しますか、それとも ID のみを比較しますか?:

>>> b == a
True

ID を最初に比較するのは理にかなっています。その通りだと思いますが、これをサポートするドキュメントはまだ見つかっていません。私が持っている最も近いものはこれです:

x==y通話x.__eq__(y)

を呼び出す前に何かが行われたかどうかはわかりませんx.__eq__(y)

4

2 に答える 2

6

ユーザー定義のクラス インスタンスの場合、isはフォールバックとして使用されます。デフォルト__eq__がオーバーライドされない場合、a == bは として評価されa is bます。これにより、比較が常に結果を持つことが保証されます (NotImplemented比較が明示的に禁止されている場合を除く)。

これは(やや斜めに-良いスポットSven Marnachデータモデルのドキュメントで参照されています(強調鉱山):

ユーザー定義のクラスには、デフォルトでメソッド__eq__()とメソッドがあります。__hash__()それらを使用すると、すべてのオブジェクトは等しくなく (それ自体を除く) 比較され、 thatとの両方を意味するような適切な値をx.__hash__()返します。x == yx is yhash(x) == hash(y)


次のようにデモンストレーションできます。

>>> class Unequal(object):
    def __eq__(self, other):
        return False


>>> ue = Unequal()
>>> ue is ue
True
>>> ue == ue
False

soの__eq__前に呼び出す必要がありますidが、:

>>> class NoEqual(object):
    pass

>>> ne = NoEqual()
>>> ne is ne
True
>>> ne == ne
True

そのため、定義されていないid場所で呼び出す必要があります。__eq__


これは CPython implementationで確認できます。

/* If neither object implements it, provide a sensible default
   for == and !=, but raise an exception for ordering. */

実装されている「賢明なデフォルト」vは、ポインタとの C レベルの等値比較でありw、これらが同じオブジェクトを指しているかどうかを返します。

于 2015-10-08T09:34:23.983 に答える
3

@jonrsharpe による回答に加えて、比較されるオブジェクトが実装されている場合、 Python が最初に ID をチェックするのは__eq__間違っています。

次の例を見てください。

>>> x = float('nan')
>>> x is x 
True
>>> x == x
False

NaN は、それ自体と比較してはならない特定のものです。ただし、この場合でも、のセマンティクスにより、x is xを返す必要があります。Trueis

于 2015-10-08T09:54:19.953 に答える