我想创建一个上下文管理器,它可以拦截给定类或此类的子类中的任何对象实例化,并对该对象执行某些操作。
我 sudo 代码可能看起来像这样:
with my_context_watchdog(my_callback, BaseClass):
obj_1 = BaseClass(name) # launch callback
obj_2 = SubClass(name) # launch callback
obj_3 = RandomClass(name) # does not launch callback
def my_callback(new_obj):
print("new object name:", new_obj.name)
我可以用Python做这样的事情吗?
最好是仅在对象完全实例化之后执行回调。
重要提示:我无法修改任何对象类,它们位于库中,我对其没有任何控制权。我只想在实例化该库的某些类时引发回调。
也许上下文管理器不是最好的主意,我愿意接受任何其他解决方案。
最佳答案
上下文管理器实际上看不到 with
block 中的代码。如果您看到一个库在做这样的“神奇”事情,那么通常在后台某个地方有一个隐藏的全局变量,并且在 with
block 内调用的函数主动与上下文管理器合作。
也就是说,您有两种选择。一种是有道理的,一种是非常丑陋的。
有意义的:
# somewhere in the context manager:
class ContextManagerReturnVal:
def instantiate(self, cls, *args, **kwargs):
obj = cls(*args, **kwargs)
if issubclass(cls, self.base_class):
self.callback(cls, *args, **kwargs)
return obj
with watchdog(callback, BaseClass) as instantiate:
obj1 = instantiate(BaseClass, name)
obj2 = instantiate(SubClass, name)
最难看的是对 BaseClass
进行猴子修补。您在评论中说您无法修改 BaseClass - 取决于您的具体含义。如果您无法修改源代码,您仍然可以在运行时修改该类,如下所示:Monkey patching a class in another module in Python
您必须存储原始的 __init__ 方法并在上下文管理器退出后返回它...这当然不推荐,因为您基本上是在不应该做的地方,并且可能会引入硬性-查找错误。
除此之外,恐怕做不到。
关于Python 上下文管理器和对象创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51867255/