2016-04-12 8 views
4

私は、インスタンスの代わりにクラスを返すPythonの関数を持っています。戻り値が特定の型のサブクラスであることを示すにはどうすればよいですか?返される型のチェックPEP 484

次の例では、私はタイプとして戻り値を設定したが、私はさらに種類がBaseClassののすべての属性していることを示したいと思います:

from typing import Dict, Any 

def class_constructor(name: str, attrs: Dict[str, Any]) -> type 
    ConstructedClass = type(name, (BaseClass,), attrs) 
    return ConstructedClass 

class BaseClass: ... 

私は(と言うことはできません... ) - > BaseClassそれはBaseClass自体ではなくBaseClassのインスタンスを示すためです。

私自身の質問に答えるには、python/typing issue #107と表示されます。今のところ、最良の解決策は次のとおりです。

from typing import Dict, Any 

class BaseClass: ... 

def class_constructor(name: str, attrs: Dict[str, Any]) -> Callable[Any, BaseClass] 
    ConstructedClass = type(name, (BaseClass,), attrs) 
    return ConstructedClass 

あなた__init__署名を知っている場合、あなたはCallable[Any, ...]に代わりAnyのものを使用することができます。 Type[T]のサポートが追加されると

ソリューションは次のようになります。

from typing import Dict, Any 

class BaseClass: ... 

def class_constructor(name: str, attrs: Dict[str, Any]) -> Type[BaseClass] 
    ConstructedClass = type(name, (BaseClass,), attrs) 
    return ConstructedClass 
+0

具体的な実行可能な例は、あなたが望んでいないものを提供できますか? – chepner

+0

mypyとPEP 484の両方で、 'Type [T]'のサポートが追加されました。 – max

答えて

0

私はあなたが単にそれと任意の子孫クラスをタグ付けする方法としてBaseClassが使用する新しいクラスを作成する必要があるだろうと思います。

class BaseClassMeta(type): 
    pass 

class BaseClass(metaclass=BaseClassMeta): 
    ... 

def class_constructor(name: str, attrs: Dict[str, Any]) -> BaseClassMeta 
    ConstructedClass = BaseClassMeta(name, (BaseClass,), attrs) 
    return ConstructedClass 
+0

結果クラスは実際には適切に機能しますが、問題は解決しません。 'BaseClassMeta(...)'は型を生成しますが、 'ConstructedClass(...)'はオブジェクトを生成するので、返される型は 'BaseClassMeta'にはなりません。私は、 ' - > Callable [[...]、BaseClass]'を使って必要なものをもう少し近づけることができます。 '...'は '__init__'関数の引数です。このコードがすべて賢明であるようにするためのクラス)。少なくともPyCharmは、返されたクラスの属性でないなら、 'ConstructedClass(...)'オブジェクトの属性を推論することができます。 – Neapolitan

+0

なぜですか?実際にはどこに 'ConstructedClass'のインスタンスを作成していますか? 'BaseClass'と' ConstructedClass'は 'BaseClassMeta'のインスタンスです。 – chepner

+0

クラスコンストラクタからの戻り値は実際には 'BaseClassMeta'のインスタンスですが、動作が異なります。つまり、 'BaseClassMeta(...) - > type'ではなく' ConstructedClass(...) - > object'です。 'class_constructor'が' BaseClassMeta'を返すと言うと、後で 'BaseClassMeta'の' MyClass'から 'obj = MyClass()'と言うと 'MyClass = class_constructor(...)'の静的解析が失敗します'は' type'関数と同じシグニチャを期待しています。 – Neapolitan

関連する問題