設定ファイルのような.pyファイルを使用したい。したがって、_{...}
_表記を使用して、文字列をキーとして使用して辞書を作成できますが、標準のpython辞書では定義の順序が失われます。
私の質問:_{...}
_表記をオーバーライドして、OrderedDict()
の代わりにdict()
を取得することは可能ですか?
DictコンストラクターをOrderedDict(_dict = OrderedDict
_)でオーバーライドするだけで機能することを期待していましたが、機能しません。
例えば:
_dict = OrderedDict
dictname = {
'B key': 'value1',
'A key': 'value2',
'C key': 'value3'
}
print dictname.items()
_
出力:
_[('B key', 'value1'), ('A key', 'value2'), ('C key', 'value3')]
_
ここにあなたが望む構文をほぼ与えるハックがあります:
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()
from nastyhacks import ordereddict
menu = ordereddict[
"about" : "about",
"login" : "login",
'signup': "signup"
]
編集:他の誰かが独自にこれを発見し、少し提供する odictliteral
パッケージをPyPIで公開しましたより完全な実装-代わりにそのパッケージを使用します
文字通り求めているものを取得するには、ファイルの構文ツリーをいじる必要があります。私はそうすることはお勧めできないと思いますが、私はしようとする誘惑に抵抗できませんでした。さあ、行きます。
まず、組み込みの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
_
この変更を適切に行うと、_candict
を上書きして、辞書表示の動作を変更します。次に例を示します。
_# test.py
from collections import OrderedDict
print {3: 4, "a": 2}
dict = OrderedDict
print {3: 4, "a": 2}
_
これで、my_execfile("test.py")
を使用してこのファイルを実行し、出力を生成できます
_{'a': 2, 3: 4}
OrderedDict([(3, 4), ('a', 2)])
_
簡単にするために、上記のコードはdict()
コンストラクターに渡されるジェネレーター式に変換する必要がある辞書の内包に触れないことに注意してください。 visit_DictComp()
メソッドをDictDisplayTransformer
クラスに追加する必要があります。上記のコード例を考えると、これは簡単なはずです。
繰り返しますが、このような言語のセマンティクスをいじることはお勧めしません。 ConfigParser
モジュールを調べましたか?
OrderedDict
は「標準python構文」ではありませんが、キーと値のペアの順序付けされたセット(標準python構文))は単純です:
_[('key1 name', 'value1'), ('key2 name', 'value2'), ('key3 name', 'value3')]
_
OrderedDict
を明示的に取得するには:
_OrderedDict([('key1 name', 'value1'), ('key2 name', 'value2'), ('key3 name', 'value3')])
_
もう1つの方法は、dictname.items()
を並べ替えることです。
_sorted(dictname.items())
_
あなたが求めていることは不可能ですが、 [〜#〜] 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)])
python 3.6、 すべての辞書はデフォルトでorderedになります です。現時点では、これはdict
の実装の詳細であり、信頼すべきではありませんが、v3.6以降では標準になる可能性があります。
挿入順序は、新しいdict
実装で常に保持されます。
>>>x = {'a': 1, 'b':2, 'c':3 }
>>>list(x.keys())
['a', 'b', 'c']
python 3.6 **kwargs
order [PEP468] およびクラス属性の順序[ PEP52 ]が保持されます。新しい コンパクトで順序付けられた辞書の実装 は、これらの両方の順序付けを実装するために使用されます。
私が見つけた1つの解決策は、python自体にパッチを適用して、dict
オブジェクトに挿入の順序を記憶させることです。
これは、あらゆる種類の構文で機能します。
x = {'a': 1, 'b':2, 'c':3 }
y = dict(a=1, b=2, c=3)
等.
ordereddict
Cの実装を https://pypi.python.org/pypi/ruamel.ordereddict/ から取得し、メインのpythonコードにマージして戻しました。
pythonインタープリターの再構築を気にしない場合は、Python 2.7.8のパッチを以下に示します。 https://github.com/fwyzard/cpython/compare/2.7。 8 ... ordereddict-2.7.8.diff .A
探しているものが使いやすい初期化構文を取得する方法である場合、OrderedDictのサブクラスを作成し、dictを更新する演算子を追加することを検討してください。次に例を示します。
from collections import OrderedDict
class OrderedMap(OrderedDict):
def __add__(self,other):
self.update(other)
return self
d = OrderedMap()+{1:2}+{4:3}+{"key":"value"}
dは-OrderedMap([(1、2)、(4、3)、( 'key'、 'value')])になります
スライス構文を使用した、もう1つの可能な構文糖の例:
class OrderedMap(OrderedDict):
def __getitem__(self, index):
if isinstance(index, slice):
self[index.start] = index.stop
return self
else:
return OrderedDict.__getitem__(self, index)
d = OrderedMap()[1:2][6:4][4:7]["a":"H"]