2015-10-14 5 views
11

Iはcollections.abc(ETC マッピングシーケンス)によって提供される基礎知識に基づいて、コレクションの様々な定義Pythonパッケージを有しています。私はPython 3.5で導入されたヒンティング・タイプの機能を利用したいと思っていますが、私はそれについての最善の方法が何であるかについて疑問を抱いています。ユーザ定義された一般的なタイプとcollections.abc

これらのクラスの1つを例として取り上げます。

from typing import TypeVar, Hashable, Mapping 

K = TypeVar("K", bound=Hashable) 
V = TypeVar("V") 

class MyMapping(Mapping[K, V]): 
    ... 

しかし、これは二つの問題提起:

    documentationはこのような何かをやって提案し、ジェネリック型にこれを有効にするには

    from collections.abc import Mapping 
    
    class MyMapping(Mapping): 
        ... 
    

    :今まで、私はこれを似た何か を持っていました

  • クラスは、すべてのmixinメソッドをcollections.abc.Mappingから削除します。私はこれを自分で実装することに対処できますが、それは最初にABCを使用する目的の一部を破ります。

  • isinstance(MyMapping(), collections.abc.Mapping)はFalseを返します。また、collections.abc.Mapping.register(MyMapping)を呼び出すと、RuntimeError( "継承サイクルの作成を拒否する")が呼び出されます。これらの問題を解決する

私の最初の試みは collections.abc.Mapping の延長に戻っていた。

from typing import TypeVar, Hashable 
from collections.abc import Mapping 

K = TypeVar("K", bound=Hashable) 
V = TypeVar("V") 

class MyMapping(Mapping[K, V]): 
    ... 

をしかし、それはをcollections.abc.Mappingとして、機能しません。ジェネリック型ではなく、サブスクリプション演算子をサポートしていません。だから私はこれを試した:

from typing import TypeVar, Hashable, Mapping 
from collections.abc import Mapping as MappingABC 

K = TypeVar("K", bound=Hashable) 
V = TypeVar("V") 

class MyMapping(MappingABC, Mapping[K, V]): 
    ... 

しかし、これは魚臭い。インポートとエイリアシングは煩雑で、結果として生じるクラスには曲がりくねったMROがあり、ABCによって提供されるミックスインメソッドにはタイピング情報はありません...

カスタムジェネリックタイプコレクションに基づいてABC?

答えて

1

[Personal Opinion™]:新しいtyping機能の作成は実際にはサポートされていません。これらは、コードの変更を必要としないように一般的なものでなければなりません。あなたのマッピングクラスは、それが任意の共通マッピング(のようなdict)で置き換えることができないので、洗練されている場合は、あなただけの自分自身を使用したほうが良いです:

def foo(bar: MyMapping) -> List: 
    pass 

代わりの

def foo(bar: Mapping[K, V]) -> List: 
    pass 

さて、あなたがしたい場合「タイプ」はtyping.Mappingであなたのクラスをチェックすることができるようにするユーザーが、あなただけのcollections.Mapping

class MyMapping(collections.abc.Mapping): 
    ... # define required methods 

isinstance(MyMapping(), typing.Mapping[K, V]) # --> True 
+0

[私の個人的なオピニオン]:私は自分自身をほのめかし静的型付けやタイプに大きなないんだけど、私は理解していくつかの人にとって魅力的なものであり、IDEや他のツールに提供できる利点があります。私はAPIライターとユーザーがオプトインすることができるオプションのレイヤーが好きです。 –

+0

私のAPIのユーザは、その関数の1つが 'MyMapping [str、int]'のオブジェクトを返すようにしたいと願っています。彼らがMyMapping、または[str、int]、またはMapping [...]を返すだけであることを伝えたい場合は、それらもすべて問題ありません。また、タイプヒントをすべてスキップしたい場合は、より多くのパワーをそれらに与えます。彼らの選択でなければなりません。 "この関数はMyMappingのインスタンスを返します"または "この関数は文字列キーと整数値を使ってマッピングを返します"と言うことができますが、2つのステートメントを混在させることはできません。それは奇妙な制限のようです。 –

+0

@MartiCongost私の指摘は、静的な型入力​​にクラスを使用してはいけないということです。クラスがマッピングであれば、 'typing.Mapping [K、V]'だけを使用する必要があります。関数に「dict」を渡すことができません – JBernardo

0

あなたの元のコードは、トンで正常に動作をサブクラス化する必要があります彼は現在のバージョンのpythonとmypyを使用しています(実装を再利用することも含めてcollections.abc.Mappingから)。

それはnot fully supported yetですので、当分の間、あなたは、bound=Hashableを削除する必要があります。

from typing import TypeVar, Hashable, Mapping 

K = TypeVar("K") 
V = TypeVar("V") 

class MyMapping(Mapping[K, V]): 
    ... 
+0

ヘッドアップありがとう。それはしばらくして、私はこれで現在作業していませんが、私はあなたが答えを受け入れることができるかどうかを試してみます。 –

関連する問題