17

を使用するときにメソッドが互いに等しいことに依存していたというバグがありましたis。そうではないことがわかりました。

>>> class What:
...     def meth(self):
...         pass

>>> What.meth is What.meth
True
>>> inst = What()
>>> inst.meth is inst.meth
False

なぜそうなのですか?通常の機能で機能します。

>>> def func(): pass
>>> func is func
True
4

2 に答える 2

26

メソッド オブジェクトは、アクセスするたびに作成されます関数は記述子として機能し、.__get__メソッドが呼び出されたときにメソッド オブジェクトを返します。

>>> What.__dict__['meth']
<function What.meth at 0x10a6f9c80>
>>> What.__dict__['meth'].__get__(What(), What)
<bound method What.meth of <__main__.What object at 0x10a6f7b10>>

Python 3.8 以降を使用している場合は、==代わりに等価性テストを使用できます。Python 3.8 以降では、.__self__および.__func__属性が同一のオブジェクトである場合、2 つのメソッドは同等です (したがって、同じ関数をラップし、同じインスタンスにバインドされている場合、両方とも でテストされますis)。

3.8 より前で==は、メソッドの実装方法に基づいてメソッドの動作に一貫性がありませんでした。Python メソッドと 2 つの C メソッド タイプの 1 つ__self__は同一性ではなく等しいかどうかで比較され、もう 1 つの C メソッド タイプは同一性で比較__self__されます。Python の問題 1617161を参照してください。

メソッドが同じ基礎となる関数を表していることをテストする必要がある場合は、それらの__func__属性をテストします。

>>> What.meth == What.meth     # functions (or unbound methods in Python 2)
True
>>> What().meth == What.meth   # bound method and function
False
>>> What().meth == What().meth # bound methods with *different* instances
False
>>> What().meth.__func__ == What().meth.__func__ # functions
True
于 2013-04-12T17:54:31.873 に答える
0

Martijn が言うように、新しいメソッドは によって生成されるオブジェクトであるため、それらのアドレス ポインターは評価.__get__と同等ではありません。usingは Python 2.7 で意図したとおりに評価されることにis注意してください。==

Python2.7
class Test(object):
    def tmethod(self):
        pass

>>> Test.meth is Test.meth
False
>>> Test.meth == Test.meth
True

>>> t = Test()
>>> t.meth is t.meth
False
>>> t.meth == t.meth
True

ただし、インスタンスから参照されるメソッドは、クラスから参照されるメソッドと同等ではないことに注意してください。これは、インスタンスからのメソッドとともに自己参照が実行されるためです。

>>> t = Test()
>>> t.meth is Test.meth
False
>>> t.meth == Test.meth
False

Python 3.3 ではis、メソッドの演算子は と同じように動作することが多い==ため、この例では代わりに期待される動作が得られます。__cmp__これは、Python 3 でのメソッド オブジェクト表現の消失とクリーン化の両方が原因です。メソッドには現在あり__eq__、参照はオンザフライで構築されたオブジェクトではないため、Python 2 の期待がなくても期待どおりの動作が行われます。

Python3.3
>>> Test.meth is Test.meth
True
>>> Test.meth == Test.meth
True
>>> Test.meth.__eq__(Test.meth)
True
于 2013-04-12T17:57:21.367 に答える