获取要在with语句中执行的命令块

ely*_*ely 4 python scope with-statement

在阅读with声明(链接)的规范时,我有一些我想要玩的东西.这不是任何生产代码或任何东西,我只是在探索,所以如果这是一个坏主意请不要太苛刻.

我想做的是抓住上面链接文档中名为"BLOCK"的文章,并在调用内部实际修补它__enter__.(请参阅链接文档,在动机和摘要部分开始之后.)

我们的想法是创建自己的即时本地命名空间.像这样的东西:

with MyNameSpace(some_object):
    print a #Should print some_object.a
    x = 4 #Should set some_object.x=4
Run Code Online (Sandbox Code Playgroud)

基本上,我希望with块内的语句从属于局部变量和赋值约定some_object.

在我的具体情况下,some_object可能是一个特殊的数据数组,它有我自己的列式操作或其他东西.在这种情况下说某些东西x = y + 5 if y > 4 else y - 2可能是一些花哨的NumPy矢量化操作,但我不需要显式调用some_object这些方法的接口.在命名空间中,表达式应该"正常工作"(但是我将它们定义为在MyNameSpace类中推断出来).

我的第一个想法是以某种方式中断with进程并获取try块中的代码.然后__enter__在调用时解释该代码,并用try其他东西替换块中的代码(可能pass如果这样可行,但可能会恢复some_object到原始变量作用域并保留其新的已更改变量).

一个简单的测试用例是这样的:

my_dict = {'a':3, 'b':2}
with MyNameSpace(my_dict):
    print a # Should print 3
    x = 5 # When the block finishes, my_dict['x'] should now be 5
Run Code Online (Sandbox Code Playgroud)

如果这个想法已存在于某个地方,我很感兴趣.

我知道分配变量的最佳实践.这是一个宠物项目,所以请假设,只是为了这个想法,我们可以忽略最佳实践.即使您不希望以这种方式分配变量,它也可能在我当前的项目中很有用.

编辑

为了澄清我可能想要做的各种棘手的事情,并且为了解决下面的答案声称无法完成,请考虑以下示例文件testLocals.py:

my_dict = {'a':1, 'b':2}
m = locals()
print m["my_dict"]['a']
m["my_dict"]['c'] = 3
print my_dict

class some_other_scope(object):
    def __init__(self, some_scope):
        x = 5
        g = locals()
        some_scope.update(g)
        some_scope["my_dict"]["d"] = 4

sos = some_other_scope(m)
print my_dict
print x
Run Code Online (Sandbox Code Playgroud)

当我以非交互方式运行时,它给出以下内容:

ely@AMDESK:~/Desktop/Programming/Python$ python testLocals.py
1
{'a': 1, 'c': 3, 'b': 2}
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
5
Run Code Online (Sandbox Code Playgroud)

Odo*_*ois 5

试试这个.

import sys 
class MyNameSpace(object):
    def __init__(self,ns):
        self.ns = ns
    def __enter__(self):
        globals().update(self.ns)
    def __exit__(self, exc_type,exc_value,traceback):
        self.ns.update(sys._getframe(1).f_locals)

my_dict = {'a':3, 'b':2} 
with MyNameSpace(my_dict) as ns:
    print(a) # Should print 3
    x = 5 # When the block finishes, my_dict['x'] should now be 5 

print(my_dict['x'])
Run Code Online (Sandbox Code Playgroud)