0

For object and function references, id and is behave as I would have expected, but for methods, they don't. The example provided is for a builtin method, but I see the same for other methods.

>>> fred = "abcd"
>>> bill = fred
>>> id(fred)
139890760324016
>>> id(bill)
139890760324016
>>> bill is fred
True
>>> harry = fred.join
>>> id(fred.join)
139890761574896
>>> id(harry)
139890760308992
>>> harry is fred.join
False
>>> fred.join
<built-in method join of str object at 0x7f3adb1393b0>
>>> harry
<built-in method join of str object at 0x7f3adb1393b0>
>>> harry == fred.join
True
>>> 
>>> def testFn():
...     return
... 
>>> mary = testFn
>>> id(testFn)
139890760327952
>>> id(mary)
139890760327952
>>> mary is testFn
True

This behavior seems to make my life more difficult, which is not something I'm used to from python. Is there a simple way to do a test for the same reference that includes methods or will I need to make methods a special case, using == for methods and is for other objects?

wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • 1
    Hmm, what are you doing that depends on the identity of methods? – Kelly Bundy Mar 01 '23 at 13:47
  • @Steven Great. You should have a banner at the top of the question where you can click something like, "Yes, this answers my question", that'll make it "official". – wjandrea Mar 02 '23 at 18:40

1 Answers1

1

For object and function references, id and is behave as I would have expected, but for methods, they don't.

That is because your expectations are not sensible. Methods accessed through an instance are a proxy object (because it wraps the object itself), which may or may not be cached by the VM.

Because of descriptors, attribute access never guarantees conservation of identity (or even equality). Though it holds for most objects, this property is an implementation detail of said object.

Is there a simple way to do a test for the same reference that includes methods

Don't. Or get it from the class rather than the instance.

or will I need to make methods a special case, using == for methods and is for other objects?

You should stop whatever you are doing. You're clearly relying on fragile implementation details which you're not bothering to get informed about.

Masklinn
  • 34,759
  • 3
  • 38
  • 57
  • Could you clarify what you mean with "Though it holds for most objects, this property is an implementation detail of said object"? What object and what property? It sounds like you're saying the id of some object might change. – Kelly Bundy Mar 01 '23 at 17:58
  • 1
    @Kelly The way I understand it, the property is "conservation of identity (or even equality)" and the object is *any* object, but "most" seems to be an overstatement due to exactly the behaviour demonstrated in the question. I think I'd rephrase it as *"Though it holds in many cases, such as `x = 10e6; x.real is x.real`, this property is an implementation detail of each object/attribute."* – wjandrea Mar 01 '23 at 18:28
  • @KellyBundy the conservation of identity for attributes of a given object. Accessing an attribute can execute arbitrary code, and return arbitrary values, even with no intermediate updates or side-effects in the attribute access. – Masklinn Mar 01 '23 at 19:02
  • Ah, ok. I thought you were talking about the method objects. – Kelly Bundy Mar 01 '23 at 19:03
  • 1
    @wjandrea I stated it holds for most cases because in near every case you have a reason to care, you're accessing an attribute which is just stored in the object's dict or slots. – Masklinn Mar 01 '23 at 19:04
  • @Masklinn Does it occur to you that one reason someone asks a question here is because they know what they've done is fragile and plan to change it when they know more. I use stackoverflow for answers to questions like this and when my search didn't find one I created my first question for others that work the way I do. Anyways, the question has been answered clearly by the reference provided by wjandrea above. – Steven Smith Mar 02 '23 at 13:44