全局范围的Python设置属性和获取属性?

全局范围的Python设置属性和获取属性?,python,variable-assignment,lookup,quoting,redefine,Python,Variable Assignment,Lookup,Quoting,Redefine,假设我需要创建自己的小型DSL,它将使用Python来描述特定的数据结构。我希望能写一些像这样的东西 f(x) = some_stuff(a,b,c) 让Python,而不是抱怨未声明的标识符或试图调用函数的一些东西,为了我的进一步方便,将其转换为文字表达式 通过使用正确重新定义的\uuuu getattr\uuuuu和\uuuu setattr\uuuuuu方法创建一个类,并按如下方式使用,可以获得合理的近似值: e = Expression() e.f[e.x] = e.some_stuf

假设我需要创建自己的小型DSL,它将使用Python来描述特定的数据结构。我希望能写一些像这样的东西

f(x) = some_stuff(a,b,c)
让Python,而不是抱怨未声明的标识符或试图调用函数的一些东西,为了我的进一步方便,将其转换为文字表达式

通过使用正确重新定义的
\uuuu getattr\uuuuu
\uuuu setattr\uuuuuu
方法创建一个类,并按如下方式使用,可以获得合理的近似值:

e = Expression()
e.f[e.x] = e.some_stuff(e.a, e.b, e.c)
@my_dsl
def definitions():
    f[x] = x*2
    f[z] = some_function(z)
    g.i  = some_object[i].method(param=value)

不过,如果有可能去掉恼人的“e”前缀,甚至避免使用[],那就太酷了。所以我想知道,是否有可能临时“重新定义”全局名称查找和分配?另一方面,可能有一些很好的软件包可以轻松实现Python表达式的这种“引用”功能?

您可能想看看Python附带的
ast
parser
模块,以解析、访问和转换输入代码的抽象语法树(或解析树)。据我所知,用Python编写的具有类似类型的预编译器。

我不确定这是否是个好主意,但我想我会的。总结如下:

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

对于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)')
其中添加定义意味着解析左手边和右手边,并做其他难看的事情。现在,这里有一种方法(不一定很好,但肯定很有趣)允许编写上述代码,如下所示:

e = Expression()
e.f[e.x] = e.some_stuff(e.a, e.b, e.c)
@my_dsl
def definitions():
    f[x] = x*2
    f[z] = some_function(z)
    g.i  = some_object[i].method(param=value)
让Python在幕后完成大部分解析。 这个想法是基于伊恩提到的简单的
exec
in
语句,加上一个骇人听闻的补充。也就是说,必须稍微调整函数的字节码,并将所有本地变量访问操作(LOAD\ U FAST)切换到环境中的变量访问(LOAD\ U NAME)

显示比解释更容易:

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


更新。这是对同一件事的更详细的解释。

谢谢,这确实是一种可能性。尽管如此,这并不完全是我想要的,因为这需要我通过将“要解析的表达式”作为字符串传递来将其与普通python分离,如果能够继续使用标准解析并简单地重新定义求值行为(
\uuu getattr\uuuu
等等),这就没有那么可怕了。“前缀"? 它们对于理解正在发生的事情似乎是绝对必要的。如果
some_stuff
不是一个函数,而是一个匿名对象的秘密方法,我很难理解任何人如何学会使用它。好吧,学会使用它是一个与适当文档无关的问题。请注意,在我的示例中,一些东西也没有引用“expression”对象的现有函数-它将在
\uuuuu getattr\uuuu
的帮助下“动态创建”。我本质上寻求的是一种创造性感语法糖的方法,它可以用更具可读性的东西来取代诸如添加新的公式(['f','x'],['some_stuff','a','b','c'])
。其中一个答案提到了Sage,看看它是如何在一个实例中使用经过修改的Python语法的。@KT:你的各种例子都在地图上。一个假设太多,一个可能对同一个对象有太多不必要的对象引用,另一个可能有太多的引号和括号。您是否可以提供任何可以显示您正试图使用标准对象类执行的工作示例的内容?你能不夸张一下吗?你能提供工作类来帮助我们简化语法吗?Ian提供了一个详尽的答案-我基本上是在寻找
exec。。在..
expression中-因此不再需要担心任何问题。如果您想更好地理解动机,那么让我补充一下,我只是在寻找一种有趣的方法,让Python“解析”某个配置文件,它基本上使用Python语法,但没有一个标识符或赋值对应于“真正的”Python对象或赋值(例如,其中一些必须由外部系统代理)。我想我得到了我的答案。尽管如此,还是感谢你的帮助!@KT:如果你不想澄清这个问题,这是否意味着你不认为普通人应该理解你的问题?我发现当人们不希望他们的问题清晰完整时,这会让人感到不安。对于其他试图解决问题的人来说,这似乎降低了他们的价值同样的问题。太棒了!“执行官…在…”或多或少就是我想要的。我现在可以把这些东西放到注释中,并在给定的函数中发生一些神奇的事情。可能不可能让它的语法比这更甜。谢谢!嘿,不幸的是,这个解决方案的工作原理不同,这取决于您从哪里获得代码对象。如果它是字符串或compile()按预期工作。但是,如果代码对象类似于my_function.func_code,则由于函数中变量绑定的特殊性,此操作将失败-无法在提供的环境中查找局部变量。字节码混乱可以克服此问题(请参阅此处的代码\u all_variables\u dynamic:)但是,这使得整个过程比它本来可能的更复杂。是的……这些问题永远不会真正停止,这就是为什么如果可能的话,最好在没有黑客的情况下在可用范围内工作。