【问题标题】:Python reflection: How to get the id of a specific instance of a method from inside itself?Python反射:如何从内部获取方法的特定实例的ID?
【发布时间】:2021-03-24 02:36:48
【问题描述】:

我不能只使用像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 保存在其他地方,这很容易,但我的问题是:有没有办法在不存储 id 的情况下从 amethod 内部进行操作?或者,如果不可能的话,除了 id 之外,还有什么可以用作 dict 键的东西吗?

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

【问题讨论】:

    标签: python oop methods dynamic reflection


    【解决方案1】:

    您似乎无法按照我想要的方式一般地在方法中获得对方法的引用,至少在没有像inspect 之类的更骇人听闻的事情的情况下没有很多麻烦。无论如何,尝试将数据存储在函数中可能是一个非常愚蠢的想法,我认为这就是为什么它很难做到。 相反,我为回调函数制作了一个薄包装类。这就是我想要的,尽管它确实需要向方法传递一个额外的参数:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-14
      • 2014-09-21
      • 2014-07-14
      • 2013-01-13
      • 2011-05-06
      • 1970-01-01
      • 2014-06-22
      • 1970-01-01
      相关资源
      最近更新 更多