fdb*_*fdb 41 python dictionary overriding ordereddictionary built-in
我想像配置文件一样使用.py文件.因此,使用{...}符号我可以使用字符串作为键创建字典,但定义顺序在标准python字典中丢失.
我的问题:是否有可能覆盖{...}符号,以便我得到一个OrderedDict()而不是dict()?
我希望用OrderedDict(dict = OrderedDict)简单地覆盖dict构造函数会起作用,但事实并非如此.
例如:
dict = OrderedDict
dictname = {
'B key': 'value1',
'A key': 'value2',
'C key': 'value3'
}
print dictname.items()
Run Code Online (Sandbox Code Playgroud)
输出:
[('B key', 'value1'), ('A key', 'value2'), ('C key', 'value3')]
Run Code Online (Sandbox Code Playgroud)
Eri*_*ric 77
这是一个几乎为您提供所需语法的黑客:
class _OrderedDictMaker(object):
def __getitem__(self, keys):
if not isinstance(keys, tuple):
keys = (keys,)
assert all(isinstance(key, slice) for key in keys)
return OrderedDict([(k.start, k.stop) for k in keys])
ordereddict = _OrderedDictMaker()
Run Code Online (Sandbox Code Playgroud)
from nastyhacks import ordereddict
menu = ordereddict[
"about" : "about",
"login" : "login",
'signup': "signup"
]
Run Code Online (Sandbox Code Playgroud)
编辑:其他人独立发现了这个,并odictliteral在PyPI 上发布了一个包,它提供了一个稍微更全面的实现 - 请改用它
Sve*_*ach 39
要真正得到你要求的东西,你必须摆弄文件的语法树.我不认为这样做是可取的,但我无法抗拒尝试的诱惑.所以我们走了.
首先,我们创建一个具有与my_execfile()内置函数类似的函数的模块execfile(),除了所有出现的字典显示,例如{3: 4, "a": 2}由对dict()构造函数的显式调用替换,例如dict([(3, 4), ('a', 2)]).(当然我们可以通过调用直接替换它们collections.OrderedDict(),但我们不想太过于干扰.)这是代码:
import ast
class DictDisplayTransformer(ast.NodeTransformer):
def visit_Dict(self, node):
self.generic_visit(node)
list_node = ast.List(
[ast.copy_location(ast.Tuple(list(x), ast.Load()), x[0])
for x in zip(node.keys, node.values)],
ast.Load())
name_node = ast.Name("dict", ast.Load())
new_node = ast.Call(ast.copy_location(name_node, node),
[ast.copy_location(list_node, node)],
[], None, None)
return ast.copy_location(new_node, node)
def my_execfile(filename, globals=None, locals=None):
if globals is None:
globals = {}
if locals is None:
locals = globals
node = ast.parse(open(filename).read())
transformed = DictDisplayTransformer().visit(node)
exec compile(transformed, filename, "exec") in globals, locals
Run Code Online (Sandbox Code Playgroud)
通过这种修改,我们可以通过覆盖来修改字典显示的行为dict.这是一个例子:
# test.py
from collections import OrderedDict
print {3: 4, "a": 2}
dict = OrderedDict
print {3: 4, "a": 2}
Run Code Online (Sandbox Code Playgroud)
现在我们可以使用运行此文件my_execfile("test.py"),产生输出
{'a': 2, 3: 4}
OrderedDict([(3, 4), ('a', 2)])
Run Code Online (Sandbox Code Playgroud)
请注意,为简单起见,上面的代码不接触字典理解,字典理解应转换为传递给dict()构造函数的生成器表达式.您需要向该类添加visit_DictComp()方法DictDisplayTransformer.鉴于上面的示例代码,这应该是直截了当的.
同样,我不推荐这种语言语义的混乱.你有没看过这个ConfigParser模块?
Aus*_*all 13
OrderedDict 不是"标准python语法",但是,一组有序的键值对(在标准python语法中)就是:
[('key1 name', 'value1'), ('key2 name', 'value2'), ('key3 name', 'value3')]
Run Code Online (Sandbox Code Playgroud)
要明确获得OrderedDict:
OrderedDict([('key1 name', 'value1'), ('key2 name', 'value2'), ('key3 name', 'value3')])
Run Code Online (Sandbox Code Playgroud)
另一种选择是排序dictname.items(),如果这就是你所需要的:
sorted(dictname.items())
Run Code Online (Sandbox Code Playgroud)
从 python 3.6 开始,所有字典都将默认排序。目前,这是一个实现细节,dict不应依赖,但它可能会在 v3.6 之后成为标准。
插入顺序始终保留在新dict实现中:
>>>x = {'a': 1, 'b':2, 'c':3 }
>>>list(x.keys())
['a', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)
从 python 3.6 开始,**kwargs顺序[PEP468]和类属性顺序 [ PEP520 ] 被保留。新的紧凑、有序的字典实现用于实现这两个的排序。
您要求的是不可能的,但如果JSON语法中的配置文件足够,您可以执行与json模块类似的操作:
>>> import json, collections
>>> d = json.JSONDecoder(object_pairs_hook = collections.OrderedDict)
>>> d.decode('{"a":5,"b":6}')
OrderedDict([(u'a', 5), (u'b', 6)])
Run Code Online (Sandbox Code Playgroud)
我找到的一个解决方案是修补 python 本身,使dict对象记住插入的顺序。
这适用于所有类型的语法:
x = {'a': 1, 'b':2, 'c':3 }
y = dict(a=1, b=2, c=3)
Run Code Online (Sandbox Code Playgroud)
等等。
我ordereddict从https://pypi.python.org/pypi/ruamel.ordereddict/获取了C 实现并合并回了主要的 python 代码。
如果您不介意重新构建 Python 解释器,这里是 Python 2.7.8 的补丁:https : //github.com/fwyzard/cpython/compare/2.7.8...ordereddict-2.7.8.diff 。一种