diff options
author | Guido van Rossum <guido@python.org> | 2016-08-06 20:46:48 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2016-08-06 20:46:48 (GMT) |
commit | abfe28b01282d5f7c79b2e3cfb33ea29f9f3656f (patch) | |
tree | 8991762655967277a864db6e150681fc6b8f0184 | |
parent | ab75e02f5c8f4035293c3ee99d9e99e3efd90928 (diff) | |
download | cpython-abfe28b01282d5f7c79b2e3cfb33ea29f9f3656f.zip cpython-abfe28b01282d5f7c79b2e3cfb33ea29f9f3656f.tar.gz cpython-abfe28b01282d5f7c79b2e3cfb33ea29f9f3656f.tar.bz2 |
Better docs for typing.Any by Michael Lee. Fixes issue #27688.
-rw-r--r-- | Doc/library/typing.rst | 80 |
1 files changed, 71 insertions, 9 deletions
diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index c870485..29211c0 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -279,17 +279,79 @@ conflict. Generic metaclasses are not supported. The :class:`Any` type --------------------- -A special kind of type is :class:`Any`. Every type is a subtype of -:class:`Any`. This is also true for the builtin type object. However, to the -static type checker these are completely different. +A special kind of type is :class:`Any`. A static type checker will treat +every type as being compatible with :class:`Any` and :class:`Any` as being +compatible with every type. -When the type of a value is :class:`object`, the type checker will reject -almost all operations on it, and assigning it to a variable (or using it as a -return value) of a more specialized type is a type error. On the other hand, -when a value has type :class:`Any`, the type checker will allow all operations -on it, and a value of type :class:`Any` can be assigned to a variable (or used -as a return value) of a more constrained type. +This means that it is possible to perform any operation or method call on a +value of type on :class:`Any` and assign it to any variable:: + from typing import Any + + a = None # type: Any + a = [] # OK + a = 2 # OK + + s = '' # type: str + s = a # OK + + def foo(item: Any) -> int: + # Typechecks; `item` could be any type, + # and that type might have a `bar` method + item.bar() + ... + +Notice that no typechecking is performed when assigning a value of type +:class:`Any` to a more precise type. For example, the static type checker did +not report an error when assigning ``a`` to ``s`` even though ``s`` was +declared to be of type :class:`str` and receives an :class:`int` value at +runtime! + +Furthermore, all functions without a return type or parameter types will +implicitly default to using :class:`Any`:: + + def legacy_parser(text): + ... + return data + + # A static type checker will treat the above + # as having the same signature as: + def legacy_parser(text: Any) -> Any: + ... + return data + +This behavior allows :class:`Any` to be used as an *escape hatch* when you +need to mix dynamically and statically typed code. + +Contrast the behavior of :class:`Any` with the behavior of :class:`object`. +Similar to :class:`Any`, every type is a subtype of :class:`object`. However, +unlike :class:`Any`, the reverse is not true: :class:`object` is *not* a +subtype of every other type. + +That means when the type of a value is :class:`object`, a type checker will +reject almost all operations on it, and assigning it to a variable (or using +it as a return value) of a more specialized type is a type error. For example:: + + def hash_a(item: object) -> int: + # Fails; an object does not have a `magic` method. + item.magic() + ... + + def hash_b(item: Any) -> int: + # Typechecks + item.magic() + ... + + # Typechecks, since ints and strs are subclasses of object + hash_a(42) + hash_a("foo") + + # Typechecks, since Any is compatible with all types + hash_b(42) + hash_b("foo") + +Use :class:`object` to indicate that a value could be any type in a typesafe +manner. Use :class:`Any` to indicate that a value is dynamically typed. Classes, functions, and decorators ---------------------------------- |