0

私は Python にいくつかのコードを持っており、そこにはたくさんのクラスがあり、それぞれに属性があります_internal_attribute。これらの属性から元のクラスへのマッピングを生成できるようにしたいと考えています。基本的に私はこれを行うことができるようにしたいと思います:

class A(object):
    _internal_attribute = 'A attribute'
class B(object):
    _internal_attribute = 'B attribute'

a_instance = magic_reverse_mapping['A attribute']()
b_instance = magic_reverse_mapping['B attribute']()

ここで欠けているのは、magic_reverse_mappingdict を生成する方法です。私は、メタクラスに A と B を生成させることが、これを行う正しい方法であるという直感を持っています。それは正しいと思いますか?

4

2 に答える 2

5

メタ クラスを使用して、クラスを に自動的に登録できますmagic_reverse_mapping

magic_reverse_mapping = {}

class MagicRegister(type):
   def __new__(meta, name, bases, dict):
      cls = type.__new__(meta, name, bases, dict)
      magic_reverse_mapping[dict['_internal_attribute']] = cls
      return cls

class A(object):
    __metaclass__ = MagicRegister
    _internal_attribute = 'A attribute'

afoo = magic_reverse_mapping['A attribute']()

または、クラスでデコレータを使用して登録することもできます。これはより読みやすく、理解しやすいと思います:

magic_reverse_mapping = {}

def magic_register(cls):
   magic_reverse_mapping[cls._internal_attribute] = cls
   return cls

@magic_register
class A(object):
    _internal_attribute = 'A attribute'

afoo = magic_reverse_mapping['A attribute']()

または、手動で行うこともできます。魔法を使わなくても、それほど多くの作業はありません。

reverse_mapping = {}

class A(object):
    _internal_attribute = 'A attribute'

reverse_mapping[A._internal_attribute] = A

さまざまなバリエーションを見ると、デコレータ バージョンが最も使いやすいと思います。

于 2009-08-12T00:02:52.283 に答える
3

そもそも適用可能なクラスのリストを格納するためにいくつかのデータ構造が必要ですが、そもそもそれを生成する必要はありません。代わりに、グローバルからクラスを読み取ることができます。objectこれは当然、最初の投稿の場合と同様に、クラスが拡張されることを前提としています。

def magic_reverse_mapping(attribute_name, attribute_value):
    classobjects = [val for val in globals().values() if isinstance(val, object)]
    attrobjects = [cls for cls in classobjects if hasattr(cls, attribute_name)]
    resultobjects = [cls for cls in attrobjects if object.__getattribute__(cls, attribute_name) == attribute_value]
    return resultobjects

magic_reverse_mapping('_internal_attribute', 'A attribute')
#output:   [<class '__main__.A'>]

複数存在する可能性があるため、これはその属性値を持つクラスのリストを返すことに注意してください。最初のものをインスタンス化する場合:

magic_reverse_mapping('_internal_attribute', 'A attribute')[0]()
#output:   <__main__.A object at 0xb7ce486c>

sthの回答とは異なり、クラスにデコレータを追加する必要はありません(ただし、適切なソリューションです)。ただし、グローバル名前空間にあるクラスを除外する方法はありません。

于 2009-08-11T23:21:40.807 に答える