我在文件中定义了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
实例。
可以使用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()