0

YAML ファイルを読み取ることで、次の Python 辞書を取得したいと考えています。

mydict = {('x','x'): 4}

また:

mydict = {['x','x']: 4}

基本的に、辞書のキーとしてタプルまたはリストが必要です。これは私が試したYAMLです:

mydict:
   !!python/tuple [e,e]: 4 # valid, but python-specific
   !!python/list [b,b]: 4 # error: "found unhashable key"
   [c,c]: 4 # error: "found unhashable key"
   !!seq [d,d]: 4 # error: "found unhashable key"

私は PyYAML を使用しているため、YAML コードは YAML1.1 構文である必要があります。または、この種のデータをテキスト ファイルに保存するためのより良い方法をお勧めできます。と思いましjson.loadたが、JSON は配列をマッピング キーとして受け入れません。

ありがとう =)

4

2 に答える 2

1

また、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 自体について、シーケンスをキーとして使用することを禁止するものは何もないと思います。

于 2013-07-29T11:18:25.383 に答える
0

Python でリストをハッシュ キーとして使用する方法はありません。それは可変です。タプルを使用する必要があります。

于 2012-11-24T03:41:17.837 に答える