This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: "is" operator doesn't work on method returned from method descriptor
Type: behavior Stage: resolved
Components: Versions: Python 3.8
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: christian.heimes, yandrieiev
Priority: normal Keywords:

Created on 2020-03-17 20:08 by yandrieiev, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (3)
msg364474 - (view) Author: Yurii (yandrieiev) * Date: 2020-03-17 20:08
I reproduced this in python 3.8 and python 3.6. The last line displays the bug itself, all other lines do the setup and pretty much explain WHY I think that is the bug.

class Class:
    def method(self): ...

instance = Class()

# expected: ids match
assert id(Class.method.__get__(None, Class)) == id(Class.method)
# expected: __eq__ returns True
assert Class.method.__get__(None, Class) == Class.method
# expected: is returns True
assert Class.method.__get__(None, Class) is Class.method

# expected: ids match
assert id(Class.method.__get__(instance, Class)) == id(instance.method)
# expected: __eq__ returns True
assert Class.method.__get__(instance, Class) == instance.method
# UNEXPECTED: is returns False, why?..
assert Class.method.__get__(instance, Class) is not instance.method  # why?
msg364477 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2020-03-17 20:56
This is not a bug. The "is" operator works as expected. A method descriptor returns a new wrapper object on each access.

CPython uses free lists to "recycle" memory locations to increase performance. id(Class.method.__get__(None, Class)) == id(Class.method) is true because the return value of "Class.method.__get__(None, Class)" is garbage collected and the memory address is reused.

See:

>>> class Class:
...     def method(self): ...
... 
>>> instance = Class()
>>> m1 = Class.method.__get__(instance, Class)
>>> m2 = instance.method
>>> id(m1) == id(m2)
False
msg364478 - (view) Author: Yurii (yandrieiev) * Date: 2020-03-17 21:17
@christian.heimes thanks for the feedback
History
Date User Action Args
2022-04-11 14:59:28adminsetgithub: 84178
2020-03-17 21:17:51yandrieievsetstatus: open -> closed
resolution: not a bug
2020-03-17 21:17:31yandrieievsetstatus: closed -> open
resolution: not a bug -> (no value)
messages: + msg364478
2020-03-17 20:56:35christian.heimessetstatus: open -> closed

nosy: + christian.heimes
messages: + msg364477

resolution: not a bug
stage: resolved
2020-03-17 20:08:08yandrieievcreate