summaryrefslogtreecommitdiffstats
path: root/Doc
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2016-08-06 20:46:48 (GMT)
committerGuido van Rossum <guido@python.org>2016-08-06 20:46:48 (GMT)
commitabfe28b01282d5f7c79b2e3cfb33ea29f9f3656f (patch)
tree8991762655967277a864db6e150681fc6b8f0184 /Doc
parentab75e02f5c8f4035293c3ee99d9e99e3efd90928 (diff)
downloadcpython-abfe28b01282d5f7c79b2e3cfb33ea29f9f3656f.zip
cpython-abfe28b01282d5f7c79b2e3cfb33ea29f9f3656f.tar.gz
cpython-abfe28b01282d5f7c79b2e3cfb33ea29f9f3656f.tar.bz2
Better docs for typing.Any by Michael Lee. Fixes issue #27688.
Diffstat (limited to 'Doc')
-rw-r--r--Doc/library/typing.rst80
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
----------------------------------