Python:特殊な型を作成するためのサブクラス `type`(例:「intのリスト」)
質問
特殊な型を作成できるクラスを作成するために、type
をサブクラス化しようとしています。例えばListType
:
ジェネラコディセタグプレ
ただし、このListOfInt
がインスタンスの作成に使用されることはありません。他のタイプと比較するために操作できるtype
のインスタンスとして使用するだけです...特に、私の場合、入力のタイプに応じて適切な操作を検索する必要があり、タイプが必要ですより正確なものを含めるため(list of int
やXML string
など)。
これが私が思いついたものです: ジェネラコディセタグプレ
上記のコードでは、abc
の使用は明らかではありません...ただし、上の例のようにサブクラスのListType
を記述したい場合は、便利になります...
基本的な機能は実際に機能します: ジェネラコディセタグプレ
しかし、t
がSpzType
のインスタンスであるかどうかを確認しようとすると、Pythonがおかしくなります:
ジェネラコディセタグプレ
pdb.pm()
で何が起こっているのかを調べたところ、次のコードでエラーが発生することがわかりました:
ジェネラコディセタグプレ
WeIrD ?!明らかに議論があります...それで、それはどういう意味ですか?何か案が ? abc
を誤用しましたか?
解決 3
kindall からのコメントのおかげで、コードを次のようにリファクタリングしました: ジェネラコディセタグプレ
したがって、基本的に、SpzType
はabc.ABCMeta
のサブクラスになり、 subclasshook はインスタンスメソッドとして実装されます。それはうまく機能し、(IMO)エレガントです!!!
編集:難しいことがありました... __subclasshook__
はclassmethodである必要があるため、classmethod関数を手動で呼び出す必要があります...そうしないと、__subclasshook__
を実装したい場合は機能しません。
他のヒント
あなたが何を達成したいのかよくわかりません。たぶん、collections
を直接使用するのではなく、abc
モジュールを使用する方が良いでしょうか?
ジェネリックコレクションクラスの詳細については、 PEP 3119
あなたがやりたいことのようなことは、おそらく次のようなクラスファクトリ関数を使用してより簡単に行うことができます。少なくとも私にとっては、操作しようとしているさまざまなレベルをまっすぐに保つことがより簡単になります。 ジェネラコディセタグプレ
ここでは、dict
をキャッシュとして使用しているため、要素タイプと機能の特定の組み合わせに対して同じクラスオブジェクトを取得できます。これにより、listOf(int) is listOf(int)
は常にTrue
になります。
これは、どのクラスでも機能する他の回答のデコレータバージョンです。デコレータは、目的の属性を持つ元のクラスのサブクラスを返すファクトリ関数を返します。このアプローチの良いところは、メタクラスを義務付けていないことです。そのため、必要に応じて、競合することなくメタクラス(ABCMeta
など)を使用できます。
基本クラスがメタクラスを使用する場合、そのメタクラスは生成されたサブクラスをインスタンス化するために使用されることにも注意してください。必要に応じて、目的のメタクラスをハードコーディングするか、メタクラスをテンプレートクラスのデコレータにするデコレータを作成することができます...それはずっと下のデコレータです!
存在する場合、クラスメソッド__classinit__()
はファクトリに渡された引数を渡されるため、クラス自体が引数を検証してその属性を設定するコードを持つことができます。 (これは、メタクラスの__init__()
の後に呼び出されます。)__classinit__()
がクラスを返す場合、このクラスは生成されたクラスの代わりにファクトリによって返されるため、この方法で生成プロシージャを拡張することもできます(たとえば、型チェックリストクラスの場合)。 、アイテムを要素タイプに強制変換する必要があるかどうかに応じて、2つの内部クラスのいずれかを返すことができます。
__classinit__()
が存在しない場合、ファクトリに渡される引数は、新しいクラスのクラス属性として設定されるだけです。
タイプが制限されたコンテナクラスを作成するのに便利なように、機能dictとは別に要素タイプを処理しました。合格しなかった場合は無視されます。
以前と同様に、ファクトリによって生成されたクラスはキャッシュされるため、同じ機能を持つクラスを呼び出すたびに、同じクラスオブジェクトインスタンスを取得できます。 ジェネラコディセタグプレ
タイプ制限(実際にはタイプ変換)リストクラスの例: ジェネラコディセタグプレ
新しいクラスの生成: ジェネラコディセタグプレ
次にインスタンス化します: ジェネラコディセタグプレ
または、クラスを作成して1つのステップでインスタンス化する: ジェネラコディセタグプレ