@@ -2144,22 +2144,142 @@ case the instance is itself a class.
21442144Emulating generic types
21452145-----------------------
21462146
2147- One can implement the generic class syntax as specified by :pep: `484 `
2148- (for example ``List[int] ``) by defining a special method:
2147+ When using :term: `type annotations<annotation> `, it is often useful to
2148+ *parameterize * a :term: `generic type ` using Python's square-brackets notation.
2149+ For example, the annotation ``list[int] `` might be used to signify a
2150+ :class: `list ` in which all the elements are of type :class: `int `.
2151+
2152+ .. seealso ::
2153+
2154+ :pep: `484 ` - Type Hints
2155+ Introducing Python's framework for type annotations
2156+
2157+ :ref: `Generic Alias Types<types-genericalias> `
2158+ Documentation for objects representing parameterized generic classes
2159+
2160+ :ref: `Generics `, :ref: `user-defined generics<user-defined-generics> ` and :class: `typing.Generic `
2161+ Documentation on how to implement generic classes that can be
2162+ parameterized at runtime and understood by static type-checkers.
2163+
2164+ A class can *generally * only be parameterized if it defines the special
2165+ class method ``__class_getitem__() ``.
21492166
21502167.. classmethod :: object.__class_getitem__(cls, key)
21512168
21522169 Return an object representing the specialization of a generic class
21532170 by type arguments found in *key *.
21542171
2155- This method is looked up on the class object itself, and when defined in
2156- the class body, this method is implicitly a class method. Note, this
2157- mechanism is primarily reserved for use with static type hints, other usage
2158- is discouraged.
2172+ When defined on a class, ``__class_getitem__() `` is automatically a class
2173+ method. As such, there is no need for it to be decorated with
2174+ :func: `@classmethod<classmethod> ` when it is defined.
21592175
2160- .. seealso ::
21612176
2162- :pep: `560 ` - Core support for typing module and generic types
2177+ The purpose of *__class_getitem__ *
2178+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2179+
2180+ The purpose of :meth: `~object.__class_getitem__ ` is to allow runtime
2181+ parameterization of standard-library generic classes in order to more easily
2182+ apply :term: `type hints<type hint> ` to these classes.
2183+
2184+ To implement custom generic classes that can be parameterized at runtime and
2185+ understood by static type-checkers, users should either inherit from a standard
2186+ library class that already implements :meth: `~object.__class_getitem__ `, or
2187+ inherit from :class: `typing.Generic `, which has its own implementation of
2188+ ``__class_getitem__() ``.
2189+
2190+ Custom implementations of :meth: `~object.__class_getitem__ ` on classes defined
2191+ outside of the standard library may not be understood by third-party
2192+ type-checkers such as mypy. Using ``__class_getitem__() `` on any class for
2193+ purposes other than type hinting is discouraged.
2194+
2195+
2196+ .. _classgetitem-versus-getitem :
2197+
2198+
2199+ *__class_getitem__ * versus *__getitem__ *
2200+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2201+
2202+ Usually, the :ref: `subscription<subscriptions> ` of an object using square
2203+ brackets will call the :meth: `~object.__getitem__ ` instance method defined on
2204+ the object's class. However, if the object being subscribed is itself a class,
2205+ the class method :meth: `~object.__class_getitem__ ` may be called instead.
2206+ ``__class_getitem__() `` should return a :ref: `GenericAlias<types-genericalias> `
2207+ object if it is properly defined.
2208+
2209+ Presented with the :term: `expression ` ``obj[x] ``, the Python interpreter
2210+ follows something like the following process to decide whether
2211+ :meth: `~object.__getitem__ ` or :meth: `~object.__class_getitem__ ` should be
2212+ called::
2213+
2214+ from inspect import isclass
2215+
2216+ def subscribe(obj, x):
2217+ """Return the result of the expression `obj[x]`"""
2218+
2219+ class_of_obj = type(obj)
2220+
2221+ # If the class of obj defines __getitem__,
2222+ # call class_of_obj.__getitem__(obj, x)
2223+ if hasattr(class_of_obj, '__getitem__'):
2224+ return class_of_obj.__getitem__(obj, x)
2225+
2226+ # Else, if obj is a class and defines __class_getitem__,
2227+ # call obj.__class_getitem__(x)
2228+ elif isclass(obj) and hasattr(obj, '__class_getitem__'):
2229+ return obj.__class_getitem__(x)
2230+
2231+ # Else, raise an exception
2232+ else:
2233+ raise TypeError(
2234+ f"'{class_of_obj.__name__}' object is not subscriptable"
2235+ )
2236+
2237+ In Python, all classes are themselves instances of other classes. The class of
2238+ a class is known as that class's :term: `metaclass `, and most classes have the
2239+ :class: `type ` class as their metaclass. :class: `type ` does not define
2240+ :meth: `~object.__getitem__ `, meaning that expressions such as ``list[int] ``,
2241+ ``dict[str, float] `` and ``tuple[str, bytes] `` all result in
2242+ :meth: `~object.__class_getitem__ ` being called::
2243+
2244+ >>> # list has class "type" as its metaclass, like most classes:
2245+ >>> type(list)
2246+ <class 'type'>
2247+ >>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes)
2248+ True
2249+ >>> # "list[int]" calls "list.__class_getitem__(int)"
2250+ >>> list[int]
2251+ list[int]
2252+ >>> # list.__class_getitem__ returns a GenericAlias object:
2253+ >>> type(list[int])
2254+ <class 'types.GenericAlias'>
2255+
2256+ However, if a class has a custom metaclass that defines
2257+ :meth: `~object.__getitem__ `, subscribing the class may result in different
2258+ behaviour. An example of this can be found in the :mod: `enum ` module::
2259+
2260+ >>> from enum import Enum
2261+ >>> class Menu(Enum):
2262+ ... """A breakfast menu"""
2263+ ... SPAM = 'spam'
2264+ ... BACON = 'bacon'
2265+ ...
2266+ >>> # Enum classes have a custom metaclass:
2267+ >>> type(Menu)
2268+ <class 'enum.EnumMeta'>
2269+ >>> # EnumMeta defines __getitem__,
2270+ >>> # so __class_getitem__ is not called,
2271+ >>> # and the result is not a GenericAlias object:
2272+ >>> Menu['SPAM']
2273+ <Menu.SPAM: 'spam'>
2274+ >>> type(Menu['SPAM'])
2275+ <enum 'Menu'>
2276+
2277+
2278+ .. seealso ::
2279+ :pep: `560 ` - Core Support for typing module and generic types
2280+ Introducing :meth: `~object.__class_getitem__ `, and outlining when a
2281+ :ref: `subscription<subscriptions> ` results in ``__class_getitem__() ``
2282+ being called instead of :meth: `~object.__getitem__ `
21632283
21642284
21652285.. _callable-types :
@@ -2259,19 +2379,27 @@ through the object's keys; for sequences, it should iterate through the values.
22592379
22602380.. method :: object.__getitem__(self, key)
22612381
2262- Called to implement evaluation of ``self[key] ``. For sequence types, the
2263- accepted keys should be integers and slice objects. Note that the special
2264- interpretation of negative indexes (if the class wishes to emulate a sequence
2265- type) is up to the :meth: `__getitem__ ` method. If *key * is of an inappropriate
2266- type, :exc: `TypeError ` may be raised; if of a value outside the set of indexes
2267- for the sequence (after any special interpretation of negative values),
2268- :exc: `IndexError ` should be raised. For mapping types, if *key * is missing (not
2269- in the container), :exc: `KeyError ` should be raised.
2382+ Called to implement evaluation of ``self[key] ``. For :term: `sequence ` types,
2383+ the accepted keys should be integers and slice objects. Note that the
2384+ special interpretation of negative indexes (if the class wishes to emulate a
2385+ :term: `sequence ` type) is up to the :meth: `__getitem__ ` method. If *key * is
2386+ of an inappropriate type, :exc: `TypeError ` may be raised; if of a value
2387+ outside the set of indexes for the sequence (after any special
2388+ interpretation of negative values), :exc: `IndexError ` should be raised. For
2389+ :term: `mapping ` types, if *key * is missing (not in the container),
2390+ :exc: `KeyError ` should be raised.
2391+
2392+ .. note ::
2393+
2394+ :keyword: `for ` loops expect that an :exc: `IndexError ` will be raised for
2395+ illegal indexes to allow proper detection of the end of the sequence.
22702396
22712397 .. note ::
22722398
2273- :keyword: `for ` loops expect that an :exc: `IndexError ` will be raised for illegal
2274- indexes to allow proper detection of the end of the sequence.
2399+ When :ref: `subscripting<subscriptions> ` a *class *, the special
2400+ class method :meth: `~object.__class_getitem__ ` may be called instead of
2401+ ``__getitem__() ``. See :ref: `classgetitem-versus-getitem ` for more
2402+ details.
22752403
22762404
22772405.. method :: object.__setitem__(self, key, value)
0 commit comments