没有直接的方法可以从语言中更改Python的语法。字典理解(或普通显示)总是会创建一个
dict,您对此无能为力。如果使用的是CPython,它将使用特殊的字节码直接生成dict,最终会调用
PyDictAPI函数和/或该API使用的相同基础函数。如果您使用的是PyPy,则这些字节码将在RPython
dict对象的顶部实现,而RPython对象则在经过编译和优化的Python之上实现
dict。等等。
有 间接的
方法可以做到,但是您不会喜欢它。如果您阅读了导入系统上的文档,您会发现是进口商搜索缓存的编译代码或调用编译器,以及编译器调用解析器,依此类推。在Python
3.3+中,该链中的几乎所有内容要么都是用纯Python编写的,要么具有替代的纯Python实现,这意味着您可以分叉代码并做自己的事情。其中包括使用构建AST的PyParsing代码解析源,或将dict理解AST节点编译为您自己的自定义字节码(而不是默认值),或者对字节码进行后处理,或者…
在许多情况下,一个导入钩子就足够了。如果没有,您可以随时编写自定义查找程序和加载程序。
如果您尚未使用Python
3.3或更高版本,我强烈建议您在使用这些东西之前先进行迁移。在较旧的版本中,它变得更困难,文档也更少,最终您将付出10倍的精力来学习每当迁移时就会过时的知识。
无论如何,如果您觉得这种方法很有趣,则可能需要看一下MacroPy。您可以从中借用一些代码,也许更重要的是,学习如何使用其中的某些功能(在文档中没有好的示例)。
或者,如果您愿意接受一些不太酷的东西,则可以使用它
MacroPy来构建一个“命令理解宏”。(请注意,MacroPy当前仅在Python
2.7中工作,而不在3.x中工作。)您不能完全得到
o{…},但是可以说od[{…}],这还不错。下载od.py,
realmain.py和
main.py,然后运行
pythonmain.py以查看其是否正常运行。关键是此代码,该代码采用
DictionaryCompAST,将其转换为
GeneratorExpr键值
Tuples上的等价形式,并将其包装
Call到to中
collections.OrderedDict:
def od(tree, **kw): pair = ast.Tuple(elts=[tree.key, tree.value]) gx = ast.GeneratorExp(elt=pair, generators=tree.generators) odict = ast.Attribute(value=ast.Name(id='collections'), attr='OrderedDict') call = ast.Call(func=odict, args=[gx], keywords=[]) return call
当然,另一种替代方法是修改Python解释器。
我建议
O{…}您一开始就放弃语法思想,而只是将普通的dict理解编译为dicts。好消息是,您实际上不需要更改语法(这超出了毛发……),只需更改以下任何一项即可:- dictcomps编译成的字节码,
- 解释器运行这些字节码的方式,或者
PyDict
类型的实现
坏消息是,尽管所有这些都比更改语法容易得多,但是扩展模块无法完成所有这些操作。(好吧,您可以通过执行与纯Python基本上相同的操作来做第一个……并且您可以通过将.so
/ .dll /
.dylib挂钩来修补您自己的函数来完成其中的任何一个操作,但这就是与在Python上进行黑客入侵完全相同的工作,以及在运行时进行钩子的额外工作。)
如果你想破解的CPython的来源,你想要的代码是
Python/compile.c,
Python/ceval.c和
Objects/dictobject.c,和开发者指南告诉你如何找到你所需要的一切。但是您可能想考虑改用PyPy源代码,因为它主要是用Python(的子集)而不是C编写的。
附带说明一下,即使一切都在Python语言级别完成,您的尝试也不会奏效。
olddict, dict = dict,OrderedDict创建一个名为绑定
dict在你的模块的全局,这 阴影 中内建的名字,但不会取代它。您 可以 替换内置 函数中的
内容(嗯,Python不能保证这一点,但是有特定于实现/版本的东西-我尝试过的每个实现/版本都可以正常工作……),但是您所做的是不是这样做的方式。



