2009-03-06 33 views
0

私はそうのように、Pythonの2.5のクラスとタイプのレジストリを持っている:既存のタイプに最も近いマッチングタイプを見つける最も良い方法は何ですか?

class ClassA(object): 
    pass 

class ClassB(ClassA): 
    pass 

MY_TYPES = { 
    basestring : 'A string', 
    int : 'An integer', 
    ClassA : 'This is ClassA or a subclass', 
} 

私は関数に型を渡すことができるようにしたい、それが中で最も一致するタイプを調べる必要があるだろう階層。したがって、strを検索すると、"A string"が返され、ClassBを検索すると、"This is ClassA or a subclass"が返されます。問題は、タイプオブジェクトのスーパークラス(または、むしろ、MROチェーンをトレースする方法)を見つける方法がわかりません。

これを処理する最良の方法は何ですか?

class ClassA(object): 
    pass 

class ClassB(ClassA): 
    pass 

print ClassB.__bases__ 
(<class '__main__.ClassA'>,) 

はいえ、intのようなものに注意してください:。__bases__を使用し、クラスのスーパークラスを取得するには

答えて

4
from inspect import getmro 
[st for cls, st in MY_TYPES.items() if cls in getmro(ClassB)] 

['This is ClassA or a subclass'] 

またはあなたが最初のマッチ(ES)発電機のバージョンでのみ興味があるなら:

(st for cls, st in MY_TYPES.iteritems() if cls in getmro(ClassB)) 
+0

nice!私はいつも検査することを忘れています...人格の欠陥か何かでなければなりません。 –

2

それらすべてのベースは<type 'object'>になります。あなたの例で挙げたdictキーと一致するようにテストと反復を行う必要があります。

また、任意のオブジェクトインスタンスでisinstanceを使用するか、パラメータでissubclassを使用して、それぞれのdictキーに対してテストすることもできます。いくつかはisinstanceとそのilkを悪魔の刻印とみなしているが、c'est la vieと考える。繰り返しますが、issubclassをintやその他の型で使用することに注意してください。おそらくあなたのdictキーを与えていくつかのアプローチを組み合わせる必要があります。

0

これは本当に一般的な機能のための仕事です。 PEAK-RulesおよびPEP 3124を参照してください。汎用関数は、引数の型、さらにはより複雑な式に基づいて任意の関数をディスパッチすることを可能にします。

あなたが本当に罰のための吸血鬼なら、chapterPractical Common Lispから目撃してください。

1

(CLSのためのST、MY_TYPES.iteritemsにおけるST()getmroでCLS(ClassBの)場合)

はそれを書くための簡単な方法は、次のようになります。

(st for cls, st in MY_TYPES.iteritems() if issubclass(ClassB, cls)) 

しかし、この「最も近い」一致が見つからない。 'object'がルックアップに含まれていれば、すべてのものに一致する可能性があります。私は...とにかく

for cls in inspect.getmro(ClassB): 
    if cls in MY_TYPES: 
     print MY_TYPES[cls] 
     break 
else: 
    print 'Dunno what it is' 

:あなたがルックアップで他のもののサブクラスをしたものを持っていた、またはあなたが多重継承をサポートしたい場合は、MROの最初だったものを選ぶ必要があるだろう一般的にコードの匂いの少しとして型のルックアップを考えて、あなたが望むことを行うためのより良い方法はありませんか?

+0

ウィジェットライブラリとデータベースライブラリを使用しています。ウィジェットを割り当てて、特定のデータベースフィールドを柔軟に表示する必要があります。 "TextWidget"を使用して "ベースストリング"を表示すると、私が見ることができる最良の方法です。また、定義する特定のデータベース・タイプに依存しません。 –

関連する問題