全局范围的Python __setattr__和__getattr__?

时间:2010-04-17 00:08:10

标签: python variable-assignment lookup quoting redefine

假设我需要创建自己的小型DSL,它将使用Python来描述某种数据结构。例如。我希望能够写出像

这样的东西
f(x) = some_stuff(a,b,c)

并拥有Python,而不是抱怨未声明的标识符或尝试调用some_stuff函数,将其转换为文字表达式以便我进一步方便。

通过使用正确重新定义的__getattr____setattr__方法创建一个类,可以得到一个合理的近似值,并按如下方式使用它:

e = Expression()
e.f[e.x] = e.some_stuff(e.a, e.b, e.c)

如果有可能摆脱恼人的“e”,那将会很酷。前缀甚至可能避免使用[]。所以我想知道,是否有可能暂时“重新定义”全局名称查找和分配?在相关的说明中,也许有很好的软件包可以轻松实现Python表达式的这种“引用”功能吗?

3 个答案:

答案 0 :(得分:3)

我不确定这是个好主意,但我想我give it a try。总结一下:

class PermissiveDict(dict):
    default = None

    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            return self.default

def exec_with_default(code, default=None):
    ns = PermissiveDict()
    ns.default = default
    exec code in ns
    return ns

答案 1 :(得分:2)

您可能希望查看Python中包含的astparser模块,以解析,访问和转换输入代码的抽象语法树(或分别为解析树)。据我所知,用Python编写的Sage mathematical system有一个类似的预编译器。

答案 2 :(得分:-1)

回应Wai的评论,这是我找到的一个有趣的解决方案。首先,为了再次解释它的作用,假设你有以下代码:

definitions = Structure()
definitions.add_definition('f[x]', 'x*2')
definitions.add_definition('f[z]', 'some_function(z)')
definitions.add_definition('g.i', 'some_object[i].method(param=value)')

添加定义意味着解析左手边和右手边以及做其他丑陋的东西。现在,这里的一个(不一定是好的,但肯定很有趣)的方法将允许编写上面的代码如下:

@my_dsl
def definitions():
    f[x] = x*2
    f[z] = some_function(z)
    g.i  = some_object[i].method(param=value)

让Python完成大部分解析工作。 这个想法是基于Ian提到的简单exec <code> in <environment>声明,其中包含一个强加的内容。也就是说,必须稍微调整函数的字节码,并将所有局部变量访问操作(LOAD_FAST)切换到环境(LOAD_NAME)的变量访问。

显示比说明更简单:http://fouryears.eu/wp-content/uploads/pydsl/

你可能想要做些各种技巧来实现它。例如,在上面链接中提供的代码中,您不能使用内置函数和语言结构,例如@my_dsl函数中的for循环和if语句。但是,您可以通过向Env类添加更多行为来实现这些功能。

更新的。 Here对同一事情的解释稍微冗长。

相关问题