タイピングでobject
を使用するのとは異なり、typing.Any
を使用することに違いはありますか?例えば:
def get_item(L: list, i: int) -> typing.Any:
return L[i]
に比べ:
def get_item(L: list, i: int) -> object:
return L[i]
はい、違いがあります。 Python 3では、すべてのオブジェクトはobject
自体を含むobject
のインスタンスですが、戻り値を無視する必要があるのはAny
ドキュメントのみですタイプチェッカーによって。
Any
タイプのdocstringは、オブジェクトがAny
のサブクラスであり、その逆も同様であることを示しています。
_>>> import typing
>>> print(typing.Any.__doc__)
Special type indicating an unconstrained type.
- Any object is an instance of Any.
- Any class is a subclass of Any.
- As a special case, Any and object are subclasses of each other.
_
ただし、適切なタイプチェッカー(isinstance()
チェックを超え、オブジェクトが実際に使用されているかどうかを検査する(== --- ==)関数内で) object
は常に受け入れられるAny
にすぐに反対できます。
タイプ
Any
の値をより正確なタイプに割り当てる場合、タイプチェックは実行されないことに注意してください。
そして
Any
の動作とobject
の動作を比較してください。Any
と同様に、すべての型はobject
のサブタイプです。ただし、Any
とは異なり、その逆は当てはまりません。オブジェクトは他のすべてのタイプのサブタイプではありません。つまり、値の型が
object
の場合、型チェッカーはそのほとんどすべての操作を拒否し、より特殊な型の変数に割り当てる(または戻り値として使用する)型です。エラー。
そしてmypyドキュメントセクションから Any vs.object :
タイプ
object
は、値として任意のタイプのインスタンスを持つことができる別のタイプです。Any
とは異なり、object
は通常の静的型(JavaのObject
に類似)であり、オブジェクト値に対して受け入れられるのは、すべての型に有効な操作のみです。
object
は cast より具体的な型にできますが、Any
は実際にすべてが意味することを意味しますと型チェッカーは、オブジェクトの使用から解放されます(後でそのようなオブジェクトをistypecheckedという名前に割り当てた場合でも)。
list
を受け入れることにより、関数を型なしのコーナーにすでにペイントしました。これは、_List[Any]
_と同じものになります。タイプチェッカーが解除され、戻り値は重要ではなくなりましたが、関数はAny
オブジェクトを含むリストを受け入れるため、適切な戻り値ここではAny
になります。
型チェックされたコードに適切に参加するには、型チェッカーが戻り値を処理できるように、入力を_List[T]
_(一般的に型付きのコンテナー)としてマークする必要があります。リストから値を取得しているので、どちらの場合はT
になります。 T
からTypeVar
を作成します。
_from typing import TypeVar, List
T = TypeVar('T')
def get_item(L: List[T], i: int) -> T:
return L[i]
_
Any
とobject
は表面的には似ていますが、実際には完全に反対です。
object
は、Pythonのメタクラス階層のrootです。すべてのクラスはobject
から継承します。つまり、object
は、ある意味で、値を指定できる最も限定的なタイプです。タイプobject
の値がある場合、呼び出すことが許可されているメソッドは、すべてのオブジェクトの一部であるメソッドのみです。例えば:
foo = 3 # type: object
# Error, not all objects have a method 'hello'
bar = foo.hello()
# OK, all objects have a __str__ method
print(str(foo))
対照的に、Any
はエスケープハッチであり、動的に型付けされたコードと静的に型付けされたコードを混在させることができます。 Any
は、最も制限の少ないタイプです。タイプAny
の値では、可能なメソッドまたは操作がすべて許可されます。例えば:
from typing import Any
foo = 3 # type: Any
# OK, foo could be any type, and that type might have a 'hello' method
# Since we have no idea what hello() is, `bar` will also have a type of Any
bar = foo.hello()
# Ok, for similar reasons
print(str(foo))
通常、Any
を試して使用する必要があるのは、次の場合のみです。
Dict[str, Any]
のタイプを与えることができます。これは、何よりも少し優れています。対照的に、値が存在する可能性のあるすべてのオブジェクトで文字通り機能する必要があることをタイプセーフな方法で示したい場合は、object
を使用します。
私の推奨は、代替手段がない場合を除いて、Any
の使用を避けることです。 Any
は譲歩です。つまり、タイプセーフな世界で実際に生活したいというダイナミズムを可能にするメカニズムです。
詳細については、以下を参照してください。
特定の例では、オブジェクトやAnyではなく、TypeVarsを使用します。あなたがしたいことは、リストに含まれているもののタイプを返したいことを示すことです。リストに常に同じタイプが含まれる場合(通常はそうです)、次のようにします。
from typing import List, TypeVar
T = TypeVar('T')
def get_item(L: List[T], i: int) -> T:
return L[i]
このようにして、get_item
関数は可能な限り最も正確な型を返します。