Python 上下文管理器和对象创建



我想创建一个上下文管理器,它将拦截来自给定类或该类的子类的任何对象实例化,并对对象执行某些操作。

我 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块中的代码。如果你看到一个库在做这样"神奇"的事情,那么后台的某个地方通常有一个隐藏的全局变量,with块内调用的函数会主动与上下文管理器合作。

也就是说,您有两种选择。一个是有道理的,一个是非常丑陋的。

有意义的那个:

# 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- 取决于您的确切意思。如果你不能修改源代码,你仍然可以在运行时修改类,如下所示: 猴子在 Python 中修补另一个模块中的类 您必须存储原始__init__方法,并在上下文管理器退出后将其返回...当然不建议这样做,因为您基本上将手指伸向不应该的地方,并且可能会引入难以发现的错误。

除此之外,恐怕做不到。

我可以看到您可以相当轻松地实现一个稍微不同的上下文管理器:

with my_context_watchdog(some_instance):
pass

。但这可能与检查器功能一样好,而不是您想要的功能。上下文管理器的魔力在于__enter__方法,因此那里可能发生的事情太多,没有任何大规模的过载。可能有一种方法可以__init__方法

您还可以创建一些可以区分类名的构造函数,并考虑将其应用于__new__方法:

def new(cls):
if cls.__name__ == 'BaseClass':
pass
# do something
else:
pass
# do a different thing

最新更新