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()
我不能只使用像 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()