我在文件中定义了一个python上下文类和一个Test
类:
class Test(object):
pass
class MyContext(object):
def __init(self):
self._vars = []
def __enter__(self):
pass
def __exit(self, ....):
pass
在使用该上下文的另一个文件中:
from somewhere import Test, MyContext
with MyContext() as ctx:
mytest = Test()
所以我想要实现的是,当我退出上下文时,我想知道创建的mytest
实例并将其添加到ctx._vars = [<instance of Test >]
中。
我不想使用ctx.add_var(mytest)
方法,我希望将这些Test
实例自动添加到ctx
实例中。
答案 0 :(得分:0)
使用Python的自省功能可以做到这一点,但是您必须知道,这并不是为with
上下文块创建的。
我同意这是一种有用的语法构造,可以“偏离”以执行所需的操作:注释“注册表”中代码块内创建的对象。
在显示如何使用上下文管理器执行此操作之前,请考虑类主体是否无法满足您的需求。以这种方式使用类主体也偏离了其主要目的,但是您可以免费使用“注册表”:
from somewhere import Test, MyContext
class ctx:
mytest = Test()
vars = ctx.__dict__.values()
为了使用上下文管理器执行此操作,您必须在with
块的开始和结尾检查局部变量。尽管这并不难,但它不会涵盖创建的Test
的所有实例-因为如果代码是这样的:
mytests = []
with Mycontext as ctx:
mytests.append(Test())
没有创建新变量-因此跟踪局部变量的代码将找不到任何内容。可以编写代码来递归地查看带有容器的变量,例如字典和列表-但随后可以将mytest()
实例添加到引用为全局变量或其他模块中的变量的容器中。
事实证明,跟踪Test
实例的可靠方法是检测Test
类本身以在注册表中注释新实例。这很容易,而且对“局部变量自省”技巧的使用也更少。
该代码类似于:
class Test(object):
pass
class MyContext(object):
def __init(self, *args):
self.vars = []
self.track = args
self.original_new = {}
def patch(self, cls_to_patch):
cls_new = getattr(cls_to_patch, "__new__")
if "__new__" in cls.__dict__:
self.original_new[cls_to_patch] = cls_new
def patched_new(cls, *args, **kwargs):
instance = cls_new(*args, **kwags)
self.vars.append(instance)
return instance
cls_to_patch.__new__ = patched_new
def restore(self, cls):
if cls in self.original_new:
# class had a very own __new_ prior to patching
cls.__new__ = self.original_new[cls]
else:
# just remove the wrapped new method, restores access to superclass `__new__`
del cls.__new__
def __enter__(self):
for cls in self.track:
self.patch(cls)
return self
def __exit(self, ....):
for cls in self.track:
self.restore(cls)
...
from somewhere import Test, MyContext
with MyContext(Test) as ctx:
mytest = Test()