2009-08-11 18 views
0

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

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_mapping辞書を生成する方法です。私はメタクラスがAとBを生成することがこれについて正しい方法であると感じています。それは正しいようですか?

答えて

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 

私はデコレータのバージョンが使用するのが最も楽しいことだと思うの異なる変形を見ます。

+0

クラスデコレータには、Python> = 2.6が必要です。 – nikow

+0

デコレータのソリューションは完璧と思われます。何らかの理由で私はクラスデコレータがPy3kだけだと思っていました。 PEP-3129は3kに含まれていると言っていて、2.6にも入っているとは言いません。 – wxs

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'>] 

つ以上があるかもしれないので、これは、その属性値を持つクラスのリストを返すことに注意してください。あなたが最初の1インスタンス化したい場合:STHの答えとは異なり

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

を、あなたは(ただし、きちんとした解決策を)あなたのクラスにデコレータを追加する必要はありません。ただし、グローバル名前空間にあるクラスを除外する方法はありません。

+0

「クラスのリスト」はまさに私が避けたいものです。つまり、新しいサブクラスを追加するたびに2つの場所に追加する必要があります。 – wxs

+0

ええと、これは編集後の方が好きです...私はデコレータの解決策をとると思います。それはもっと明白で、魔法のように感じることはありません。 – wxs

+0

@wxs:ありがとうございます。あなたが正しいと言いました... sthの解決策はPythonicです。 –

関連する問題