65

タイピングtyping.Anyとは対照的に使用することに違いはありますか? object例えば:

def get_item(L: list, i: int) -> typing.Any:
    return L[i]

に比べ:

def get_item(L: list, i: int) -> object:
    return L[i]
4

2 に答える 2

75

はい、違いがあります。Python 3 では、すべてのオブジェクトは、それ自体objectを含めて のインスタンスですが、戻り値がタイプチェッカーによって無視されるべきであるというドキュメントだけがあります。objectAny

Anyタイプ docstring は、 object が のサブクラスで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タイプのドキュメントから:

Anytype の値をより正確な型に代入する場合、型チェックは実行されないことに注意してください。

の動作Anyと の動作を比較してobjectください。と同様にAny、すべてのタイプは のサブタイプですobject。ただし、 とは異なりAny、その逆は当てはまりません。オブジェクトは、他のすべての型のサブタイプではありません。

つまり、値の型が の場合object、型チェッカーはその値に対するほとんどすべての操作を拒否し、それをより特殊な型の変数に割り当てる (または戻り値として使用する) と、型エラーになります。

および mypy ドキュメント セクションAny vs. objectから:

objectは、任意の型のインスタンスを値として持つことができる別の型です。とは異なりAnyobjectは通常の静的型 ( ObjectJava と同様) であり、すべての型に対して有効な操作のみがオブジェクト値に対して受け入れられます。

objectより具体的な型にキャストできますが、Any実際には何でもあり、型チェッカーがオブジェクトの使用から解放されることを意味します (後でそのようなオブジェクトを型チェックされた名前に割り当てたとしても)

を受け入れることで、型付けされていないコーナーに関数を既に描画しました。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]
于 2016-10-02T12:43:19.963 に答える
20

Anyobjectは表面的には似ていますが、実際にはまったく反対の意味を持っています。

objectPython のメタクラス階層のルートです。すべての単一クラスは から継承しobjectます。これはobject、ある意味で、値を与えることができる最も制限的な型であることを意味します。type の値を持っている場合、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は最も制限の少ないタイプです。 type の値に対して、考えられるすべてのメソッドまたは操作が許可されます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があります...

  1. 動的に型付けされたコードと静的に型付けされたコードを混合する方法として。たとえば、多くの動的で複雑な関数があり、それらすべてを完全に静的に型付けする時間がない場合は、それらに Any の戻り値の型を与えるだけで解決できます。(別の言い方をすれば、Any は型チェックされていないコードベースを型付きコードベースに段階的に移行するのに役立つ便利なツールです)。
  2. 型付けが難しい式に型を与える方法として。たとえば、Python の型注釈は現在、再帰型をサポートしていないため、任意の JSON dict などを入力することが難しくなっています。一時的な手段として、JSON 辞書に のタイプを指定することをお勧めします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関数は可能な限り正確な型を返します。

于 2016-10-02T20:37:09.620 に答える