また、Eclipse/PyDev でデバッガーを使用し、返された YAML オブジェクトの構造を調べて、これを調査しました。リストではなく Python タプルを使用するように YAML オブジェクトを再構成することで、Python 固有の型を使用せずに、ハッシュ不可能なキーに関する特定のエラーを回避できることがわかりましたが、これは解決策であるという錯覚にすぎません。PyYAML の辞書へのキーは MappingNode でなければなりません。これは Python の値のタプルとして実装できますが、内部的にはまだセットとして扱われます (つまり、一意化と並べ替えの対象となります)。これは、異なるタプル ((a,a,b)、(a,b,a)、(b,a) など) が同じキーとして扱われる可能性があることを意味しますが、これは望ましくありません。
情報のために、これは私がしたことです。次のような YAML シーケンスに遭遇したときに、リストではなくタプルを使用して新しい MappingNode を構築する Python クラスを定義しました。
class Key(yaml.YAMLObject):
yaml_tag = "tag:example.com:2013:Key"
@classmethod
def from_yaml(cls, loader, node):
if isinstance(node, yaml.SequenceNode):
new_values = []
for v in node.value:
new_values.append( (v, yaml.ScalarNode(tag=u'tag:yaml.org,2002:null'), value=u'')) )
node = yaml.MappingNode(tag=node.tag, value=tuple(new_values))
return loader.construct_yaml_object(node,cls)
次に、YAML データで次のようなシーケンス キーのキーにこのクラスを使用しました。
!<tag:example.com:2013:Key> [a, b]: 3
また:
%TAG !mytags! tag:example.com:2013:
---
......
!mytags!Key [a, b]: 3
ただし、説明したように、これではシーケンスが期待どおりに保持されません。個人的には、このコード/アプローチを実際のアプリケーションでは使用しません。
シーケンスではなくセットを使用する方が安全だと思われますが、あなたが尋ねたものとはまったく異なります. これは、言語に依存しない YAML バージョン 1.1 の型のセット型を使用します。上記のシーケンス タイプに類似したアプローチを使用しましたが、PyYAML は MappingType のキーに Python リストを使用するため、次のようなタプルに変更するだけで済みました。
class Key(yaml.YAMLObject):
yaml_tag = "tag:example.com:2013:Key"
@classmethod
def from_yaml(cls, loader, node):
if isinstance(node, yaml.MappingNode):
node.value = tuple(node.value)
return loader.construct_yaml_object(node, cls)
次のように、セットを YAML データのキーとして使用します。
!mytags!Key {a, b}: 3
これはすべて、私には PyYAML の制限のように見えます。理論的には、YAML 自体について、シーケンスをキーとして使用することを禁止するものは何もないと思います。