2

どうやってこのような状況に陥ったのか、聞かないでください。というクラスがあるとしましょうccollection

このクラスには、実行時に次の属性があります。

ccollection.a.b.x = 1
ccollection.a.b.y = 3
ccollection.a.b.z = 4
...
ccollection.a.c = 3
ccollection.b = 3

このクラスは、上記のように動的にセットアップされます。そのため、事前にクラスの属性を知る方法はありません。

次に、このクラスのすべての属性を出力したいと思います。次に例を示します。

ccollection.a.b印刷する必要があります

ccollection.a.b.x = 1
ccollection.a.b.y = 3
ccollection.a.b.z = 4

そして ccollection.a印刷する必要があります

ccollection.a.b.x = 1
ccollection.a.b.y = 3
ccollection.a.b.z = 4
ccollection.a.c = 3

私はあなたがアイデアを得ると思います。各印刷は、同じレベル以下のすべての要素の印刷を開始する必要があります。すべての属性を再帰的にトラバースする方法を探しています (これはツリーのようなデータ構造です)

4

2 に答える 2

1

この状況は本当にリファクタリングを必要とします。コンテナとして設計されていないオブジェクトを使用しています。代わりに、dict や dict を継承するクラスなどのコンテナを使用してください。


現在のセットアップを使用する必要がある場合、最も有望なアプローチは dir を使用するように見えるというBlckknghtに同意します。

class CCollection(object):
  def get_children_strings(self):
    list_of_strings = []
    for attr_name in dir(self):
      if attr_name not in dir(CCollection()):
        attr = getattr(self, attr_name)
        if hasattr(attr, 'get_children_strings'):
          list_of_strings.extend(["." + attr_name + child_string for child_string in attr.get_children_strings()])
        else:
          list_of_strings.append("." + attr_name + " = " + str(attr))
    return list_of_strings

  def print_tree(self, prefix):
    print [prefix + s for s in self.get_children_strings()]

その後、次のことができます

m = CCollection()
m.a = CCollection()
m.a.b = CCollection()
m.a.b.x = 1
m.a.b.y = 2
m.a.c = 3
m.d = 4

m.print_tree("m")
m.a.print_tree("m.a")
m.a.b.print_tree("m.a.b")

出力を取得します。

>>> m.print_tree("m")
['m.a.b.x = 1', 'm.a.b.y = 2', 'm.a.c = 3', 'm.d = 4']
>>> m.a.print_tree("m.a")
['m.a.b.x = 1', 'm.a.b.y = 2', 'm.a.c = 3']
>>> m.a.b.print_tree("m.a.b")
['m.a.b.x = 1', 'm.a.b.y = 2']

これをさらに進めるには、ツリー トラバーサル関数を含むクラスを使用することをお勧めします。親ノードを取得する関数、ループがないことの保証、およびノー​​ドの名前を保持するクラス変数があれば、関数へのprefix引数を介して現在渡されている情報を自動的に生成できます。print_tree

于 2013-07-10T18:37:41.613 に答える
0

属性アクセスを備えたツリーのような構造が必要なようです。これは、サブクラスdict化して適切な を設定し、必要な__getattr__アクセス__setattr__API を取得すると同時に、必要な印刷を行うことで実行できます。

また、 をオーバーライドして、__str__希望どおりに印刷することもできます。

編集:

これを簡単に説明すると、次のようになります。

class DictTree( object ):
    _children = {}

    def __getattr__( self, name ):
        if not name in self._children:
            self._children[name] = DictTree()
        return self._children[name]

    def __setattr__( self, name, v ):
        self._children[name] = v

上記の作品は、あなたが望むアクセスとAPIインターフェースを提供しますが、それを印刷すると、RuntimeError: maximum recursion depth exceeded がどのように機能しているのかが原因です__getattr__. 上記のコードを微調整してこの問題が発生しないようにすると、必要なものが得られるはずです。修正には__str__メソッドが含まれます。

于 2012-11-14T15:52:25.683 に答える