Python 反思:如何从内部获取方法的特定实例的 ID?

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

我不能只使用像 id(self.methodname) 这样简单的东西,因为场景比那复杂一点,因为我正在做时髦的动态东西。我会尽量把整个情况解释清楚。

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()

首先我们有两个类。其中之一有一个字典,它将包含作为值的函数和作为键的那些函数的 id。在实际程序中,这是为了存储回调函数,fun_dict 取而代之的是类似 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

到目前为止一切顺利。所有这些都按预期工作:我们现在有一个方法 bound_to_b 同时绑定到 两个 对象,并且它已存储在 b 的 fun_dict 中。是的,我知道这是一种可怕的代码,但这是一个学习项目,所以别担心,没有人会接触到它。

但现在假设我稍后想从 b 中删除绑定方法。也就是说,从 b.fun_dict 中删除它的引用。如果我从外部执行此操作并将 id 保存在其他地方,这很容易,但我的问题是:有没有办法从 amethod 内部执行此操作而不存储 id?或者,如果不可能,是否有除 id 之外的其他东西可以用作使它成为可能的 dict 键?

print(id(self.amethod)) 实际上每次都打印不同的内存位置,所以没有帮助。 dir(bound_to_b) 里面的其他东西也没有向我跳出来。

似乎您无法按照我想要的方式在方法中获得对方法的引用,至少在没有大量处理 inspect 等更棘手的事情的情况下是这样的。无论如何,尝试将数据存储在函数中可能是一个非常愚蠢的想法,我认为这就是为什么它很难做到的原因。 相反,我为回调函数制作了一个薄包装器 class。这就是我想要的,尽管它确实需要向方法传递一个额外的参数:

import types
class Callback:
    def __init__(self, f):
        self.f = f
    def __call__(self, *args, **kwargs):
        kwargs["cbid"] = id(self)
        self.f(*args, **kwargs)


class A:
    def __init__(self):
        self.ax = 10
    def amethod(self, other, cbid=None):
        print("from inside amethod")
        other.fun_dict.pop(cbid)

class B:
    def __init__(self):
        self.fun_dict = {}
        self.bx = 20
    def run_in_dict(self):
        for fn in list(self.fun_dict.values()):
            print("before:", self.fun_dict)
            fn()
            print("after:", self.fun_dict)

a = A()
b = B()
bound = Callback(types.MethodType(a.amethod, b))
b.fun_dict[id(bound)] = bound
b.run_in_dict()