Very strange behavior of operator 'is' with methods

前端 未结 2 931
情歌与酒
情歌与酒 2021-02-01 12:51

Why is the first result False, should it not be True?

>>> from collections import OrderedDict
>>> OrderedDict.__repr_         


        
相关标签:
2条回答
  • 2021-02-01 13:29

    For user-defined functions, in Python 2 unbound and bound methods are created on demand, through the descriptor protocol; OrderedDict.__repr__ is such a method object, as the wrapped function is implemented as a pure-Python function.

    The descriptor protocol will call the __get__ method on objects that support it, so __repr__.__get__() is called whenever you try to access OrderedDict.__repr__; for classes None (no instance) and the class object itself are passed in. Because you get a new method object each time the function __get__ method is invoked, is fails. It is not the same method object.

    dict.__repr__ is not a custom Python function but a C function, and its __get__ descriptor method essentially just returns self when accessed on the class. Accessing the attribute gives you the same object each time, so is works:

    >>> dict.__repr__.__get__(None, dict) is dict.__repr__  # None means no instance
    True
    

    Methods have a __func__ attribute referencing the wrapped function, use that to test for identity:

    >>> OrderedDict.__repr__
    <unbound method OrderedDict.__repr__>
    >>> OrderedDict.__repr__.__func__
    <function __repr__ at 0x102c2f1b8>
    >>> OrderedDict.__repr__.__func__.__get__(None, OrderedDict)
    <unbound method OrderedDict.__repr__>
    >>> OrderedDict.__repr__.__func__ is OrderedDict.__repr__.__func__
    True
    

    Python 3 does away with unbound methods, function.__get__(None, classobj) returns the function object itself (so it behaves like dict.__repr__ does). But you will see the same behaviour with bound methods, methods retrieved from an instance.

    0 讨论(0)
  • 2021-02-01 13:48

    The two OrderedDict.__repr__ are not bound to the same object. If you try:

     OrderedDict.__repr__ == OrderedDict.__repr__
    

    you'll see that they have the same value.

    0 讨论(0)
提交回复
热议问题