samedi 12 décembre 2020

Python reflection: How to get the id of a specific instance of a method from inside itself?

I can't just use something straightforward like id(self.methodname) because the scenario is a little more complicated than that since I'm doing funky dynamic stuff. I'll try to explain the whole situation clearly.

class A:
     def __init__(self):
         self.ax = 10
     def amethod(self, other):
         print(self.ax)
         print(other.bx)

class B:
     def __init__(self):
         self.fun_dict = {}
         self.bx = 20
     def run_in_dict(self):
         for fn in self.fun_dict.values():
             fn()

First we have two classes. One of them has a dictionary that will contain functions as values and those function's ids as keys. In the actual program this is for storing callback functions, and fun_dict is instead named something like on_receiving.

a = A()
b = B()
import types
bound_to_b = types.MethodType(a.amethod, b)
print(bound_to_b)  # <bound method A.amethod of <__main__.B object at 0x7fdcdacf1850>>
print(bound_to_b())  # prints 10 and 20
b.fun_dict[id(bound_to_b)] = bound_to_b
b.run_in_dict() # also prints 10 and 20
a.ax = 2
b.run_in_dict() # prints 2 and 20, as expected

So far so good. All of this is working as intended: we now have a method bound_to_b that's bound to two objects simultaneously, and it's been stored in b's fun_dict. Yes, I know this is kind of horrible code but it's a learning project so don't worry, nobody will be exposed to it.

But now let's say I later want to remove the bound method from b. That is, remove its reference from b.fun_dict. This is easy enough if I'm doing it from outside and have the id saved somewhere else, but my question is: Is there a way to do it from inside amethod without storing the id? Or if it's not possible, is there something other than the id that can be used as a dict key that would make it possible?

print(id(self.amethod)) in fact prints a different memory position every time, so it doesn't help. Nothing else inside dir(bound_to_b) jumps out at me either.





Aucun commentaire:

Enregistrer un commentaire